package com.alibaba.citrus.cr.order.open.api.facade.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.lock.RedisLock;
import com.alibaba.citrus.cr.common.util.ThreadPoolUtil;
import com.alibaba.citrus.cr.order.open.api.facade.common.until.CheckUtil;
import com.alibaba.citrus.cr.order.open.api.facade.service.handler.AbstractAllocateOrderCreateHandler;
import com.alibaba.citrus.cr.unified.inventory.contants.FeaturesKey;
import com.alibaba.citrus.cr.unified.inventory.contants.UnifiedInventoryKey;
import com.alibaba.citrus.cr.unified.inventory.utils.InfoUtil;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.BatchGetReq;
import com.alibaba.cz.base.tool.FeatureUtil;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.SearchOrderDetailReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentDetailGetRes;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentGetRes;
import com.alibaba.cloud.retail.delivery.api.service.bcfulfillment.FulfillmentOrderAbilityService;
import com.alibaba.cz.base.tool.FeatureUtil;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.feature.Features;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByOutCodes2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByOutCodes2Response;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.crunifiedinventory.api.allocateorderread.service.AllocateOrderReadService;
import com.epoch.app.crunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.dto.LoadAllocateApplyOrderByCodeRequest;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.model.AllocateApplyOrder;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorder.service.AllocateApplyOrderService;
import com.epoch.app.crunifiedinventory.domain.allocateapplyorderdetail.service.AllocateApplyOrderDetailService;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.AllocateOrderLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.BatchQueryByCodeListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.UpdateFeaturesRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.model.AllocateOrder;
import com.epoch.app.crunifiedinventory.domain.allocateorder.service.AllocateOrderService;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.AllocateOrderDetailLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.BatchQueryDetailByAllocateOrderCodeListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.AllocateOrderDetailLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.UpdateQuantityAndBizFeaturesRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.model.AllocateOrderDetail;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.service.AllocateOrderDetailService;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderDetailsQueryRequest;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSaveRequest;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSubmitRequest;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSubmitSAPRequest;
import com.epoch.app.crunifiedinventory.dto.response.*;
import com.epoch.app.crunifiedinventory.model.dto.*;
import com.epoch.app.crunifiedinventory.model.enums.AllocateOrderStatus;
import com.epoch.app.crunifiedinventory.model.enums.FulfillmentTypeEnum;
import com.epoch.app.crunifiedinventory.sdo.AllocateOrderDetailSDO;
import com.epoch.app.crunifiedinventory.sdo.enums.AllocateOrderTypeEnum;
import com.epoch.app.mninventorycenter.model.dto.WarehouseQueryRequest;
import com.epoch.app.mninventorycenter.model.dto.WarehouseQueryResponse;
import com.epoch.app.mninventorycenter.model.dto.*;
import com.epoch.app.mninventorycenter.model.dto.DictionaryResponse;
import com.epoch.app.mninventorycenter.model.dto.WarehouseQueryRequest;
import com.epoch.app.mninventorycenter.model.dto.WarehouseQueryResponse;
import com.epoch.app.mninventorycenter.service.MnInventoryCenterService;
import com.epoch.app.mninventorycenter.transferorderwrite.service.TransferOrderWriteService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Primary
public class TransferOrderWriteServiceImpl implements TransferOrderWriteService {

    private static final List<String> EDITABLE_STATUS = Lists.newArrayList(
            AllocateOrderStatus.DRAFT.getValue().toString(),
            AllocateOrderStatus.Shipment_Processing.getValue().toString(),
            AllocateOrderStatus.Part_Shipped.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue().toString()
    );

    private static final List<String> REMARK_ONLY_STATUS = Lists.newArrayList(
            AllocateOrderStatus.Shipment_Processing.getValue().toString(),
            AllocateOrderStatus.Part_Shipped.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue().toString(),
            AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue().toString()
    );



    private Log log = Log.getLogger(TransferOrderWriteServiceImpl.class);

    @Resource
    private AllocateOrderWriteService allocateOrderWriteService;

    @Resource
    private MnInventoryCenterService mnInventoryCenterService;

    @Resource
    private AllocateOrderReadService allocateOrderReadService;

    @Resource
    private AllocateOrderService allocateOrderService;

    @Resource
    private AllocateApplyOrderService allocateApplyOrderService;

    @Resource
    private AllocateOrderDetailService allocateOrderDetailService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private AllocateApplyOrderDetailService allocateApplyOrderDetailService;

    @Autowired
    private List<AbstractAllocateOrderCreateHandler> allocateOrderCreateHandlers;

    @DubboReference
    private FulfillmentOrderAbilityService fulfillmentOrderAbilityService;

    private static final String FROM_SYS_GROUP = "fromSys";
    private static final String BUSINESS_TYPE_GROUP = "businessType";
    private static final String ALLOCATE_ORDER_TAG = "allocateOrderTag";
    private static final String CLOSE_REASON = "refuseReason";

    private static final List<Integer> CLOSEABLE_STATUS = Lists.newArrayList(
            AllocateOrderStatus.Shipment_Processing.getValue(), AllocateOrderStatus.Part_Shipped.getValue(),
            AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue(), AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue(),
            AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue(), AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue());


    private static final String FULFILLMENT_TYPE = "fulfillmentType";
;
    @Override
    @FacadeInvoker(value = "提交调拨单")
    public Result<Boolean> submitAllocateOrder(TransferOrderSubmitRequest request) {
        log.info("TransferOrderWriteService_submitAllocateOrder:{}",request);
        //校验
        String msg = checkSubmitNull(request);
        if (StringUtil.isNotEmpty(msg)){
            log.error("TransferOrderWriteService_submitAllocateOrder，非空校验异常：{}",msg);
            return Result.fail("10000",msg);
        }
        if (!checkDictionary(FROM_SYS_GROUP,request.getFromSys())){
            log.error("TransferOrderWriteService_submitAllocateOrder，来源系统错误");
            return Result.fail("10000","来源系统错误");
        }
        if (!checkDictionary(BUSINESS_TYPE_GROUP,request.getBusinessType())){
            log.error("TransferOrderWriteService_submitAllocateOrder，业态错误");
            return Result.fail("10000","业态错误");
        }
        //查询货品明细
        AllocateOrderDetailsQueryRequest queryRequest = new AllocateOrderDetailsQueryRequest();
        queryRequest.setCode(request.getTransferForecastOrderCode());
        queryRequest.setFromSys(request.getFromSys());
        queryRequest.setBusinessType(request.getBusinessType());
        log.info("TransferOrderWriteService_submitAllocateOrder,allocateOrderReadService.query_request:{}",queryRequest);
        Result<AllocateOrderDetailsQueryResponse> allocateOrderDetailsQueryResponseResult = allocateOrderReadService.query(queryRequest);
        if(allocateOrderDetailsQueryResponseResult.getResult() == null){
            return Result.fail("10001","调拨单不存在");
        }
        if(allocateOrderDetailsQueryResponseResult.getResult().getCode() == null){
            return Result.fail("10001","调拨单不存在");
        }
        AllocateOrderDetailsQueryResponse result = allocateOrderDetailsQueryResponseResult.getResult();
        if(!(ObjectUtil.equals(result.getStatus(), AllocateOrderStatus.DRAFT.getValue().toString())
                || ObjectUtil.equals(result.getStatus(), AllocateOrderStatus.WAIT_PUSH.getValue().toString()))){
            return Result.fail("10003","草稿和推送状态才可以提交");
        }
        //拓传
        AllocateOrderDetailsQueryResponse result1 = allocateOrderDetailsQueryResponseResult.getResult();
        List<AllocateOrderScItemDetailDTO> allocateOrderScItemDetailDTOS = result1.getAllocateOrderScItemDetailDTOS();
        List<AllocateOrderScItemDetail> collect = allocateOrderScItemDetailDTOS.stream().map(x -> {
            AllocateOrderScItemDetail allocateOrderScItemDetail = new AllocateOrderScItemDetail();
            BeanUtils.copyProperties(x,allocateOrderScItemDetail);
            allocateOrderScItemDetail.setExpectedProductionDate(x.getExpectedProductionDate());
            allocateOrderScItemDetail.setProductDate(x.getProductDate());
            allocateOrderScItemDetail.setGoodsId(x.getGoodsId());
            allocateOrderScItemDetail.setScItemId(x.getScItemId());
            allocateOrderScItemDetail.setTitle(x.getTitle());
            allocateOrderScItemDetail.setUnit(x.getUnit());
            allocateOrderScItemDetail.setQuantity(x.getQuantity());
            allocateOrderScItemDetail.setAllocateApplyOrderLineNo(x.getApplyQuantity());
            allocateOrderScItemDetail.setProductDate(x.getProductDate());
            allocateOrderScItemDetail.setConfirmedQuantity(allocateOrderScItemDetail.getConfirmedQuantity());
            allocateOrderScItemDetail.setThirdLineNo(x.getThirdLineNo());
            return allocateOrderScItemDetail;
        }).collect(Collectors.toList());
        AllocateOrderSubmitRequest submitRequest = new AllocateOrderSubmitRequest();
        submitRequest.setCode(request.getTransferForecastOrderCode());
        submitRequest.setAllocateOrderScItemDetails(collect);
        submitRequest.setDocDate(dateToString(result.getDocDate()));
        submitRequest.setUpdater(request.getUpdater());
        log.info("TransferOrderWriteService_submitAllocateOrder，extension request：{}",submitRequest);
        Result<AllocateOrderSubmitResponse> response = allocateOrderWriteService.submitNotCheck(submitRequest);
        log.info("TransferOrderWriteService_submitAllocateOrder，extension：request：{}",response);
        if (!response.isSuccess()){
            return Result.fail("10005",response.getMessage());
        }
        return Result.success(true);
    }

    @Override
    @FacadeInvoker(value = "取消调拨单")
    public Result<Boolean> cancelAllocateOrder(TransferOrderCancelRequest request) {
        log.info("TransferOrderWriteService_cancelAllocateOrder:{}",request);
        //校验
        String msg = checkCancelNull(request);
        if (StringUtil.isNotEmpty(msg)){
            log.error("TransferOrderWriteService_cancelAllocateOrder,checkNonNullError:{}",msg);
            return Result.fail("10000",msg);
        }
        if (!checkDictionary(FROM_SYS_GROUP,request.getFromSys())){
            log.error("TransferOrderWriteService_cancelAllocateOrder,checkFromSysError:{}",msg);
            return Result.fail("10000","系统来源错误");
        }
        if (!checkDictionary(BUSINESS_TYPE_GROUP,request.getBusinessType())){
            log.error("TransferOrderWriteService_cancelAllocateOrder,businessTypeError:{}",msg);
            return Result.fail("10000","业态错误");
        }
//        if (!checkTransferForecastOrderCode(request.getTransferForecastOrderCode())){
//            log.error("TransferOrderWriteService_cancelAllocateOrder,checkTransferForecastOrderCodeError:{}",msg);
//            return Result.fail("10000","调拨单号有误");
//        }
        AllocateOrderDetailsQueryRequest requestDetail= new AllocateOrderDetailsQueryRequest();
        requestDetail.setCode(request.getTransferForecastOrderCode());
        requestDetail.setBusinessType(request.getBusinessType());;
        requestDetail.setFromSys(request.getFromSys());
        Result<AllocateOrderDetailsQueryResponse> responseResult = allocateOrderReadService.query(requestDetail);
        if(responseResult.getResult() == null){
            return Result.fail("10001","调拨单不存在");
        }
        if(responseResult.getResult().getCode() == null){
            return Result.fail("10001","调拨单不存在");
        }
        AllocateOrderDetailsQueryResponse result = responseResult.getResult();

        if(!(ObjectUtil.equals(result.getStatus(), AllocateOrderStatus.DRAFT.getValue().toString())
                || ObjectUtil.equals(result.getStatus(), AllocateOrderStatus.WAIT_PUSH.getValue().toString()))){
            return Result.fail("10003","草稿和推送状态才可以取消");
        }
        //拓传
        AllocateOrderCancelRequest cancelRequest = new AllocateOrderCancelRequest();
        cancelRequest.setCode(request.getTransferForecastOrderCode());
        cancelRequest.setUpdater(request.getUpdater());
        log.info("TransferOrderWriteService_cancelAllocateOrder,extension request:{}",request);
        Result<AllocateOrderCancelResponse> response = allocateOrderWriteService.cancel(cancelRequest);
        log.info("TransferOrderWriteService_cancelAllocateOrder,extension response:{}",response);
        if (!response.isSuccess()){
            return Result.fail(response.getErrorCode(),response.getMessage());
        }
        return Result.success(true);
    }

    /**
     * 校验字典
     * @param group
     * @param code
     * @return
     */
    private boolean checkDictionary(String group, String code) {
        DictionaryQueryRequest request = new DictionaryQueryRequest();
        request.setGroup(group);
        Result<List<DictionaryResponse>> result = mnInventoryCenterService.queryDictionaryDataListApi(request);
        Set<String> businessTypeSet = result.getResult().stream()
                .map(DictionaryResponse::getCode)
                .collect(Collectors.toSet());
        return businessTypeSet.contains(code);
    }

    /**
     * 校验调拨单号
     * @param transferForecastOrderCode code
     * @return boolean
     */
    private boolean checkTransferForecastOrderCode(String transferForecastOrderCode) {
        AllocateOrderDetailsQueryRequest request = new AllocateOrderDetailsQueryRequest();
        request.setCode(transferForecastOrderCode);
        Result<AllocateOrderDetailsQueryResponse> result = allocateOrderReadService.query(request);
        if (Objects.nonNull(result.getResult())){
            return true;
        }else {
            return false;
        }
    }

    private String checkSubmitNull(TransferOrderSubmitRequest request){
        if (StringUtil.isBlank(request.getTransferForecastOrderCode()) ){
            return "调拨单号不可为空";
        }
        if (request.getTransferForecastOrderCode().length() >32 ){
            return "调拨单号字段长度不能大于32";
        }
        if (StringUtil.isBlank(request.getFromSys())){
            return "系统来源不可为空";
        }
        if (request.getFromSys().length() >32 ){
            return "系统来源字段长度不能大于32";
        }
        if (StringUtil.isBlank(request.getBusinessType())){
            return "业态不可为空";
        }
        if (request.getBusinessType().length() >32 ){
            return "业态字段长度不能大于32";
        }
        return null;
    }

    private String checkCancelNull(TransferOrderCancelRequest request){
        if (StringUtil.isBlank(request.getTransferForecastOrderCode())){
            return "调拨单号不可为空";
        }
        if (request.getTransferForecastOrderCode().length() >32){
            return "调拨单号字段长度不能大于32";
        }
        if (StringUtil.isBlank(request.getFromSys())){
            return "系统来源不可为空";
        }
        if (request.getFromSys().length() >32){
            return "系统来源字段长度不能大于32";
        }
        if (StringUtil.isBlank(request.getBusinessType())){
            return "业态不可为空";
        }
        if (request.getBusinessType().length() >32){
            return "业态字段长度不能大于32";
        }
        return null;
    }

    @Override
    @FacadeInvoker(value = "调拨单创建")
    public Result<TransferOrderCreateResponse> createAllocateOrder(TransferOrderCreateRequest transferOrderCreateRequest){
        StopWatch stopWatch = new StopWatch();
        log.info("createAllocateApplyOrder,request:{}", JSON.toJSON(transferOrderCreateRequest));
        stopWatch.start("checkCreateRequest");
        String message = checkCreateAllocateApplyOrder(transferOrderCreateRequest);
        stopWatch.stop();
        if(message != null){
            return Result.fail( "OTS-05-001-10-16-001", message);
        }
        String key = transferOrderCreateRequest.getFromSys() + "_" + transferOrderCreateRequest.getRequestId();
        //请求幂等
        try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(),
                "createAllocateOrder" + key,
                5000,10000)) {
            if (!lock.lock()){
                return Result.fail( "OTS-05-001-10-16-040", "不能重复提交调拨单创建");
            }
            stopWatch.start("idemCheck");
            Result<List<AllocateOrder>> idempotentResult = allocateOrderService.loadAllocateOrderList(AllocateOrderLoadListRequest
                    .newAllocateOrderLoadListRequestBuilder()
                    .fromSys(transferOrderCreateRequest.getFromSys())
                    .requestId(transferOrderCreateRequest.getRequestId()).build());
            stopWatch.stop();
            if (CollectionUtils.isNotEmpty(idempotentResult.getResult())) {
                return Result.fail("OTS-05-001-10-16-040", "单据已存在，请勿重复请求");
            }
            stopWatch.start("goodsCheck");
            TransferOrderCreateResponse transferOrderCreateResponse = new TransferOrderCreateResponse();
            List<String> goodsCode = transferOrderCreateRequest.getTransferOrderDetailList()
                    .stream().map(TransferOrderDetailRequest::getGoodsCode).collect(Collectors.toList());
            Map<String, ScItemResponse> scItemInfoMap = getScItemInfoList(goodsCode);
            stopWatch.stop();
            if(CollectionUtil.isEmpty(scItemInfoMap.values())){
                log.info("goods is null ");
                return Result.fail("OTS-05-001-10-16-053","货品不存在");
            }

            // 校验提报销售组织
            stopWatch.start("checkApplyOrg");
            BaselineGetOrganizationByOutCodes2Request request = new BaselineGetOrganizationByOutCodes2Request();
            request.setOutCodes(Lists.newArrayList(transferOrderCreateRequest.getApplyOrgId()));
            BaselineGetOrganizationByOutCodes2Response orgResponse = baseDataService.baselineGetOrganizationByOutCodes2(request);
            stopWatch.stop();
            if (!Boolean.TRUE.equals(orgResponse.getSuccess()) || CollectionUtils.isEmpty(orgResponse.getResult())) {
                return Result.fail("OTS-05-001-10-16-053","提报销售组织不存在");
            }
            // 过滤组合货品
            List<ScItemResponse> typeList = scItemInfoMap.values().stream().filter(x ->x.getType() == 1).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(typeList)){
                return Result.fail("OTS-05-001-10-16-053","不支持组合货品");
            }
            // -1禁用 -2删除 不可用, 1可用
            List<ScItemResponse> statusList = scItemInfoMap.values().stream().filter(x ->x.getStatus() !=1).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(statusList)){
                return Result.fail("OTS-05-001-10-16-053","货品状态不可用");
            }
            //货品单位校验
            String scItemMessage = CheckUtil.checkScItemTransferOrder(transferOrderCreateRequest.getTransferOrderDetailList(), scItemInfoMap);
            if(scItemMessage != null){
                return Result.fail("OTS-05-001-10-16-053",scItemMessage);
            }
            // 仓库code转ID
            stopWatch.start("checkWarehouse");
            WarehouseQueryResponse receiveLogicWareId = getWarehouseInfo(transferOrderCreateRequest.getReceiveLogicWareCode());
            WarehouseQueryResponse deliveryLogicWareId = getWarehouseInfo(transferOrderCreateRequest.getDeliveryLogicWareCode());
            // 仓库校验
            String wareHouseMessage = CheckUtil.checkWareHouse(transferOrderCreateRequest.getTransferOrderType(), receiveLogicWareId, deliveryLogicWareId);
            stopWatch.stop();
            if(wareHouseMessage != null){
                return Result.fail("OTS-05-001-10-16-051",wareHouseMessage);
            }

            // 关联单号校验，若传了，校验存在性
            if (StringUtils.isNotBlank(transferOrderCreateRequest.getRelatedAllocateOrderCode())){
                stopWatch.start("checkRelatedOrder");
                Result<List<AllocateOrder>> relatedOrderResult = allocateOrderService.loadAllocateOrderList(AllocateOrderLoadListRequest
                        .newAllocateOrderLoadListRequestBuilder()
                        //2024.04.07 查询原单不增加来源系统条件
//                        .fromSys(transferOrderCreateRequest.getFromSys())
                        .code(transferOrderCreateRequest.getRelatedAllocateOrderCode()).build());

                // 有数据返回时调拨单查询接口的isSuccess仍为false...
                if (!relatedOrderResult.isSuccess() && CollectionUtils.isEmpty(relatedOrderResult.getResult())) {
                    return Result.fail("OTS-05-001-10-16-052", "关联单号不存在");
                }

                AllocateOrderDetailLoadListRequest detailLoadListRequest = new AllocateOrderDetailLoadListRequest();
                detailLoadListRequest.setAllocateOrderCode(transferOrderCreateRequest.getRelatedAllocateOrderCode());
                detailLoadListRequest.setSize(1000);
                detailLoadListRequest.setLimit(1000);
                Result<List<AllocateOrderDetail>> listResult = allocateOrderDetailService.loadAllocateOrderDetailList(detailLoadListRequest);
                for (TransferOrderDetailRequest detailRequest : transferOrderCreateRequest.getTransferOrderDetailList()) {
                    if (StringUtils.isEmpty(detailRequest.getRelatedAllocateSubOrderNo())) {
                        return Result.fail("OTS-05-001-10-16-054", "关联单号存在时需要传递关联单行号");
                    }

                    // 有数据返回时调拨单详情查询接口的isSuccess也为false...
                    if (!listResult.isSuccess() && CollectionUtils.isEmpty(listResult.getResult())) {
                        return Result.fail("OTS-05-001-10-16-055", "查询关联单子单出错");
                    }

                }
                Set<String> existSet = listResult.getResult().stream().map(AllocateOrderDetail::getLineNo).collect(Collectors.toSet()).stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.toSet());
                Set<String> newSet = transferOrderCreateRequest.getTransferOrderDetailList().stream().map(TransferOrderDetailRequest::getRelatedAllocateSubOrderNo).collect(Collectors.toSet());
                boolean notMatch = Nullable.stream(newSet).anyMatch(s -> !existSet.contains(s));
                if (notMatch){
                    return Result.fail("OTS-05-001-10-16-055", "部分关联单子单不存在");
                }
//                if (!existSet.containsAll(newSet)) {
//                    return Result.fail("OTS-05-001-10-16-055", "部分关联单子单不存在");
//                }
                stopWatch.stop();
            }
            // 调拨预报单校验
            if (StringUtils.isNotEmpty(transferOrderCreateRequest.getAllocateApplyOrderCode())) {
                stopWatch.start("checkApplyOrder");
                AllocateApplyOrder allocateApplyOrder = allocateApplyOrderService.loadAllocateApplyOrderByCode(LoadAllocateApplyOrderByCodeRequest.builder()
                        .code(transferOrderCreateRequest.getAllocateApplyOrderCode()).build());
                if (allocateApplyOrder == null || allocateApplyOrder.getId() == null) {
                    return Result.fail("OTS-05-001-10-16-055", "调拨预报单不存在");
}
                transferOrderCreateRequest.setAllocateApplyOrderId(allocateApplyOrder.getId().toString());
                stopWatch.stop();
            }
            // 运输方式校验
            if (StringUtils.isNotBlank(transferOrderCreateRequest.getShipMethodCode())) {
                String shipMethodCode = transferOrderCreateRequest.getShipMethodCode();
                List<String> list = new ArrayList<>();
                for (int i = 1; i < 10; i++) {
                    list.add("0" + i);
                }
                if (!list.contains(shipMethodCode)) {
                    return Result.fail("OTS-05-001-10-16-055", "运输方式不存在");
                }

                // 如果是铁运或者海运，需要查询收货逻辑仓库对应的货场仓信息
                if ("02".equals(shipMethodCode) || "03".equals(shipMethodCode)) {
                    Map<String, String> bizFeatures = receiveLogicWareId.getBizFeatures();
                    if (MapUtils.isEmpty(bizFeatures) || StringUtils.isBlank(bizFeatures.get("freightYardCode"))) {
                        return Result.fail("OTS-05-001-10-16-055", "收货逻辑仓库对应的货场仓信息不存在");
                    }
                    transferOrderCreateRequest.setTransferWarehouseId(bizFeatures.get("freightYardCode"));
                }
            }

            // 根据类型组装创建参数并创建
            stopWatch.start("createAllocateOrder");
            for (AbstractAllocateOrderCreateHandler handler : allocateOrderCreateHandlers) {
                if (handler.support(transferOrderCreateRequest)) {
                    handler.check(transferOrderCreateRequest);
                    transferOrderCreateResponse = handler.handle(transferOrderCreateRequest, scItemInfoMap, receiveLogicWareId, deliveryLogicWareId);
                }
            }
            stopWatch.stop();
            // 提交调拨单
            if(Boolean.parseBoolean(transferOrderCreateRequest.getSubmitFlag())){
                stopWatch.start("submitAllocateOrder");
                submitAllocateOrder(transferOrderCreateResponse.getTransferOrderCode());
                stopWatch.stop();
            }
            log.info("createAllocateOrder stopWatch "+stopWatch.prettyPrint());
            return Result.success(transferOrderCreateResponse);
        }catch (Throwable e) {
            log.error("TransferForecastOrderWriteService|createAllocateOrder|error|req={} ", JSON.toJSON(transferOrderCreateRequest), e);
            return Result.fail("OTS-05-001-10-16-055","创建调拨单失败:" + e.getMessage());
        }

    }

    /**
     * 从仓库(features)中获取销售组织编码（sapOrgCode），业务单元（sapCompanyCode）
     *
     * @param receiveLogicWare  收货仓
     * @param deliveryLogicWare 发货仓
     * @return features (receiveCompanyCode:收货仓业务单元;receiveSapOrgCode:收货仓销售组织;shipCompanyCode:发货仓业务单元;shipSapOrgCode:发货仓销售组织)
     */
    private String getFeatures(WarehouseQueryResponse receiveLogicWare, WarehouseQueryResponse deliveryLogicWare, Map<String, String> features, boolean freightYard) {

        Map<String, String> newFeaturesMap;
        if (MapUtils.isNotEmpty(features)) {
            newFeaturesMap = features;
        } else {
            newFeaturesMap = new HashMap<>();
        }
        if (receiveLogicWare == null || deliveryLogicWare == null) {
            return newFeaturesMap.toString();
        }
        Map<String, String> receiveLogicWareMap = receiveLogicWare.getFeatures();
        Map<String, String> deliveryLogicWareMap = deliveryLogicWare.getFeatures();

        if(receiveLogicWareMap.get("sapCompanyCode") != null){
            newFeaturesMap.put("receiveCompanyCode", receiveLogicWareMap.get("sapCompanyCode"));
        }
        if(receiveLogicWareMap.get("sapOrgCode") != null){
            newFeaturesMap.put("receiveSapOrgCode", receiveLogicWareMap.get("sapOrgCode"));
        }
        if(deliveryLogicWareMap.get("sapCompanyCode") != null){
            newFeaturesMap.put("shipCompanyCode", deliveryLogicWareMap.get("sapCompanyCode"));
        }
        if(deliveryLogicWareMap.get("sapOrgCode") != null){
            newFeaturesMap.put("shipSapOrgCode", deliveryLogicWareMap.get("sapOrgCode"));
        }
        if (freightYard) {
            newFeaturesMap.put("freightYardReceive", "true");
        } else {
            newFeaturesMap.remove("freightYardReceive");
        }

        return FeatureUtil.toString(newFeaturesMap);
    }

    private Map<String, String> getBizFeature(WarehouseQueryResponse deliveryLogic, WarehouseQueryResponse receiveLogic) {
        Map<String, String> bizFeatures = new HashMap<>();
        // features 收发货仓的工厂编码和库存地点
        if (deliveryLogic != null) {
            WmsSDO shipWmsSDO = InfoUtil.getWmsSDO(deliveryLogic.getId());
            bizFeatures.put(FeaturesKey.DELIVERY_FACTORY_CODE,shipWmsSDO.getFactoryCode());
            bizFeatures.put(FeaturesKey.DELIVERY_STORAGE_LOCATION_CODE,shipWmsSDO.getInventoryCode());
        }

        if (receiveLogic != null) {
            WmsSDO receiveWmsSDO = InfoUtil.getWmsSDO(receiveLogic.getId());
            bizFeatures.put(FeaturesKey.RECEIVE_FACTORY_CODE,receiveWmsSDO.getFactoryCode());
            bizFeatures.put(FeaturesKey.RECEIVE_STORAGE_LOCATION_CODE,receiveWmsSDO.getInventoryCode());
        }

        return bizFeatures;
    }

    /**
     * 调拨单提交
     * @param code 调拨单编码
     */
    private Boolean submitAllocateOrder(String code){
        AllocateOrderLoadListRequest request = AllocateOrderLoadListRequest.newAllocateOrderLoadListRequestBuilder().code(code).build();
        Result<List<AllocateOrder>> listResult = allocateOrderService.loadAllocateOrderList(request);
        AllocateOrder allocateOrder = listResult.getResult().get(0);
        if (allocateOrder == null) {
            return Boolean.FALSE;
        }
        AllocateOrderSubmitSAPRequest submitSAPRequest = new AllocateOrderSubmitSAPRequest();
        submitSAPRequest.setId(allocateOrder.getId().toString());
        try {
            Result<AllocateOrderSubmitSAPResponse> submitResult = allocateOrderWriteService.submitSAP(submitSAPRequest);
            return submitResult.isSuccess();
        } catch (Exception e) {
            log.error("transferOrderWriteService|submitAllocateOrder|error|request={}", JSON.toJSONString(submitSAPRequest), e);
            return Boolean.FALSE;
        }
    }

    private String dateToString(Date date){
        if(ObjectUtil.isEmpty(date)){
            return null;
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }

    private String date2String(Date date) {
        if(ObjectUtil.isEmpty(date)){
            return null;
        }
        return new SimpleDateFormat("yyyy-MM-dd").format(date);
    }

    private String  checkCreateAllocateApplyOrder(TransferOrderCreateRequest transferOrderCreateRequest) {

        if (StringUtil.isBlank(transferOrderCreateRequest.getFromSys())){
            return "来源系统不能为空";
        }
        if (transferOrderCreateRequest.getFromSys().length() >16){
            return "来源系统字段长度不能大于16";
        }
        if (StringUtil.isBlank(transferOrderCreateRequest.getBusinessType())){
            return "业态不能为空";
        }
        if (transferOrderCreateRequest.getBusinessType().length() > 16){
            return "业态字段长度不能大于16";
        }
        if (ObjectUtil.isEmpty(transferOrderCreateRequest.getTransferOrderType())){
            return "调拨单类型不能为空";
        }
        if(transferOrderCreateRequest.getTransferOrderType()>100 || transferOrderCreateRequest.getTransferOrderType()< 0){
            return "调拨单类型非法";
        }
        AllocateOrderTypeEnum allocateOrderTypeEnumType = CheckUtil.getAllocateOrderTypeEnumType(transferOrderCreateRequest.getTransferOrderType());
        if(allocateOrderTypeEnumType == null){
            return "调拨单类型不存在";
        }
        if (StrUtil.isBlank(transferOrderCreateRequest.getReturnFlag())){
            return "是否退单不能为空";
        }
        if (transferOrderCreateRequest.getReturnFlag().length() > 10) {
            return "是否退单长度不能超过10";
        }
        if (!transferOrderCreateRequest.getReturnFlag().matches("^true|false$")){
            return "是否退单格式错误";
        }
        if (StringUtil.isBlank(transferOrderCreateRequest.getReceiveLogicWareCode())){
            return "收货逻辑仓不能为空";
        }
        if (transferOrderCreateRequest.getReceiveLogicWareCode().length() > 32){
            return "收货逻辑仓字段长度不能大于32";
        }
        if (StringUtil.isBlank(transferOrderCreateRequest.getDeliveryLogicWareCode())){
            return "发货逻辑仓不能为空";
        }
        if (transferOrderCreateRequest.getDeliveryLogicWareCode().length() >32){
            return "发货逻辑仓字段长度不能大于32";
        }
        if (StrUtil.isBlank(transferOrderCreateRequest.getOrderDate())){
            return "单据日期不能为空";
        }
        if (transferOrderCreateRequest.getOrderDate().length() != 10) {
            return "单据日期长度不能超过10或小于10";
        }
        if (!CheckUtil.isLegalDateNew(transferOrderCreateRequest.getOrderDate())){
            return "单据日期格式错误";
        }
        if (StrUtil.isBlank(transferOrderCreateRequest.getSubmitFlag())){
            return "是否提交不能为空";
        }
        if (transferOrderCreateRequest.getSubmitFlag().length() > 5){
            return "是否提交长度不能超过5";
        }
        if (!transferOrderCreateRequest.getSubmitFlag().matches("^true|false$")){
            return "是否提交格式不正确";
        }

        if (StrUtil.isBlank(transferOrderCreateRequest.getExpectedDeliveryDate())){
            return "期望交货日期不能为空";
        }
        if (transferOrderCreateRequest.getExpectedDeliveryDate().length() != 10) {
            return "期望交货日期长度不能大于或小于10";
        }
        if (!CheckUtil.isLegalDateNew(transferOrderCreateRequest.getExpectedDeliveryDate())){
            return "期望交货日期格式错误";
        }
        if (StringUtil.isBlank(transferOrderCreateRequest.getShipMethodCode())){
            return "运输方式不能为空";
        }
        if(transferOrderCreateRequest.getShipMethodCode().length() > 32){
            return "运输方式字段长度不能大于32";
        }

        if (StringUtil.isBlank(transferOrderCreateRequest.getRequestId())){
            return "请求编码不能为空";
        }
        if(transferOrderCreateRequest.getRequestId().length() >32){
            return "请求编码长度不能大于32";
        }

        if (StringUtil.isBlank(transferOrderCreateRequest.getThirdAllocateOrderId())){
            return "来源单号不能为空";
        }
        if(transferOrderCreateRequest.getThirdAllocateOrderId().length() >32){
            return "来源单号长度不能大于32";
        }

        if (StringUtil.isNotEmpty(transferOrderCreateRequest.getHeadRemark())){
            if(transferOrderCreateRequest.getHeadRemark().length() >200){
                return "抬头备注不能超过200字";
            }
        }
        if (StringUtils.isNotBlank(transferOrderCreateRequest.getRelatedAllocateOrderCode())) {
            if (transferOrderCreateRequest.getRelatedAllocateOrderCode().length() > 32) {
                return "关联单号字段长度不能大于32";
            }
        }
        if (StringUtils.isNotBlank(transferOrderCreateRequest.getBizFeatures())) {
            if (transferOrderCreateRequest.getBizFeatures().length() > 1024){
                return "主单扩展字段长度不能大于1024";
            }
            try {
                Map<String, String> featureMap = JSONObject.parseObject(transferOrderCreateRequest.getBizFeatures(), new TypeReference<Map<String, String>>() {
                });
                transferOrderCreateRequest.setBizFeatures(Features.newFeatures(featureMap).toString());
            } catch (Throwable t) {
                log.error("AbstractAllocateOrderCreateHandler_getAllocateOrderCreateRequest_main_error:", t);
                return "主单扩展字段格式需要为json格式";
            }
        }
        if(CollectionUtil.isEmpty(transferOrderCreateRequest.getTransferOrderDetailList())){
            return "调拨单详情不能为空";
        }

        if (transferOrderCreateRequest.getTransferOrderDetailList().size() > 100) {
            return "调拨单详情元素数量不能超过100";
        }

        for(TransferOrderDetailRequest x: transferOrderCreateRequest.getTransferOrderDetailList()){
            if(StringUtil.isBlank(x.getGoodsCode())){
                return "货品编码不能为空";
            }
            if(x.getGoodsCode().length() >32){
                return "货品编码字段长度不能大于32";
            }
            if(StringUtil.isBlank(x.getQuantity())){
                return "货品数量不能为空";
            }
            if(!StringUtils.isNumeric(x.getQuantity())){
                return "货品数量类型不对";
            }
            if (Long.parseLong(x.getQuantity()) > Integer.MAX_VALUE) {
                return "货品数量不能大于2147483647";
            }
            if (Long.parseLong(x.getQuantity()) < 1) {
                return "货品数量不能小于等于0";
            }
            if(StringUtil.isNotEmpty(x.getLineRemark())){
                if(x.getLineRemark().length() >200){
                    return "行备注长度不能超过200";
                }
            }
            if(StringUtil.isBlank(x.getUnit())){
                return "单位不能为空";
            }
            if(x.getUnit().length() >32){
                return "单位字段长度不能大于32";
            }
            if(StringUtil.isBlank(x.getOutDetailLineNo())){
                return "来源单行号不能为空";
            }
            if(x.getOutDetailLineNo().length() >32){
                return "来源单行号长度不能大于32";
            }
            //不传，设置默认值当天
            if (StringUtils.isEmpty(x.getProductDate())) {
//                x.setProductDate(date2String(new Date()));
            } else {
                if (x.getProductDate().length() != 10){
                    return "生产日期长度不能大于10或小于10";
                }
                if (!CheckUtil.isLegalDateNew(x.getProductDate())) {
                    return "生产日期格式错误";
                }
            }

            if (StringUtils.isNotBlank(transferOrderCreateRequest.getRelatedAllocateOrderCode())) {
                if (StringUtils.isBlank(x.getRelatedAllocateSubOrderNo())) {
                    return "关联单号不为空时，关联单行号不能为空";
                }
                if (x.getRelatedAllocateSubOrderNo().length() > 32) {
                    return  "关联单行号长度不能大于32";
                }
            } else {
                if (StringUtils.isNotBlank(x.getRelatedAllocateSubOrderNo())) {
                    return  "关联单号不能为空";
                }
            }

            if (StringUtils.isNotBlank(x.getBizFeatures())) {
                if (x.getBizFeatures().length() > 1024){
                    return "子单扩展字段长度不能大于1024";
                }
                try {
                    Map<String, String> featureMap = JSONObject.parseObject(x.getBizFeatures(), new TypeReference<Map<String, String>>() {
                    });
                    x.setBizFeatures(Features.newFeatures(featureMap).toString());
                } catch (Throwable t) {
                    log.error("AbstractAllocateOrderCreateHandler_getAllocateOrderCreateRequest_detail_error:", t);
                    return "子单扩展字段格式需要为json格式";
                }
            }
        }
        List<String> collect = transferOrderCreateRequest.getTransferOrderDetailList()
                .stream().map(TransferOrderDetailRequest::getOutDetailLineNo).distinct().collect(Collectors.toList());
        if(transferOrderCreateRequest.getTransferOrderDetailList().size() > collect.size()){
            return "外部行号不能重复";
        }
        if (!checkDictionary(FROM_SYS_GROUP,transferOrderCreateRequest.getFromSys())){
            return "来源系统错误";
        }
        if (!checkDictionary(BUSINESS_TYPE_GROUP,transferOrderCreateRequest.getBusinessType())){
            return "业态错误";
        }
        if (StringUtil.isBlank(transferOrderCreateRequest.getRequestId())){
            return "请求id不能为空";
        }
        String fulfillmentTypeCode = transferOrderCreateRequest.getFulfillmentTypeCode();
        if (StringUtils.isBlank(fulfillmentTypeCode)) {
            return "履约方式不能为空";
        }
        if (StringUtils.isNotBlank(fulfillmentTypeCode)) {
            if (fulfillmentTypeCode.length() > 4) {
                return  "履约方式长度不能大于4";
            }

            if (!checkDictionary(FULFILLMENT_TYPE,fulfillmentTypeCode)) {
                return "履约方式非法";
            }
        }

        if (StringUtils.isBlank(transferOrderCreateRequest.getApplyOrgId())) {
            return "销售组织不能为空";
        }

        if (transferOrderCreateRequest.getApplyOrgId().length() > 32) {
            return "销售组织长度不能大于32";
        }

        if (StringUtils.isBlank(transferOrderCreateRequest.getProductGroupCode())) {
            return "产品组不能为空";
        }

        if (transferOrderCreateRequest.getProductGroupCode().length() > 32) {
            return "产品组长度不能大于32";
        }

        if (!checkDictionary("productionGroup", transferOrderCreateRequest.getProductGroupCode())) {
            return "产品组错误";
        }

        if (StringUtils.isBlank(transferOrderCreateRequest.getCreator())) {
            return "创建人不能为空";
        }

        if (transferOrderCreateRequest.getCreator().length() > 32) {
            return "创建人长度不能大于32";
        }

        if (StringUtils.isNotBlank(transferOrderCreateRequest.getTakeEffectDate())) {
            if (transferOrderCreateRequest.getTakeEffectDate().length() != 10) {
                return "生效日期长度不能大于或小于10";
            }
            if (!CheckUtil.isLegalDateNew(transferOrderCreateRequest.getTakeEffectDate())) {
                return "生效日期格式错误";
            }
        }

        if (StringUtils.isNotBlank(transferOrderCreateRequest.getHeadRemark())) {
            if (transferOrderCreateRequest.getHeadRemark().length() > 200) {
                return "主单备注长度不能超过200";
            }
        }

        List<String> orderTag = transferOrderCreateRequest.getOrderTag();
        if (CollectionUtils.isNotEmpty(orderTag)) {
            if (orderTag.size() > 10) {
                return "订单标签列表数量不能大于10";
            }
            for (String tag : orderTag) {
                if (tag.length() > 32) {
                    return "订单标签长度不能大于32";
                }
            }
            List<String> collect1 = orderTag.stream().map(String::trim).distinct().collect(Collectors.toList());
            if (collect1.size() != orderTag.size()) {
                return "订单标签不能重复";
            }
            for (String tag : collect1) {
                if (!checkDictionary(ALLOCATE_ORDER_TAG, tag)){
                    return "订单标签不合法";
                }
            }
            transferOrderCreateRequest.setOrderTag(collect1);
        }

        if (StringUtils.isNotBlank(transferOrderCreateRequest.getPriority())) {
            if (transferOrderCreateRequest.getPriority().length() > 4) {
                return "履约优先级长度不能大于4";
            }
            ArrayList<String> legalList = Lists.newArrayList("1", "100");
            if (!legalList.contains(transferOrderCreateRequest.getPriority())) {
                return "履约优先级非法";
            }

        }

        if (StringUtils.isNotEmpty(transferOrderCreateRequest.getAllocateApplyOrderCode())) {
            if (transferOrderCreateRequest.getAllocateApplyOrderCode().length() > 32) {
                return "预报单号长度不能大于32";
            }
        }

        return null;
    }


    /**
     * 通过货品外部编码（goodsCode）查询货品详情goodsInfo(scItem)  getScItemInfoList
     * 校验该货品编码主数据存在且为可用状态，同时不支持组合产品，若单据中存在组合产品接口中直接报错
     */
    public Map<String, ScItemResponse> getScItemInfoList(List<String> outerIdList){
        log.info("getScItemInfoList:{}",JSON.toJSON(outerIdList));
        ScItemSearchReqAbilityDTO scItemSearchReqAbilityDTO1 = new ScItemSearchReqAbilityDTO();
        scItemSearchReqAbilityDTO1.setOuterIdList(outerIdList);
        Result<List<ScItemResponse>> listResult = mnInventoryCenterService.searchScItemFromDbList(scItemSearchReqAbilityDTO1);
        log.info("getScItemInfoList_result:{}",JSON.toJSON(listResult));
        List<ScItemResponse> scItemList = listResult.getResult();
        if(CollectionUtil.isEmpty(scItemList)){
            return new HashMap<>();
        }
        return scItemList.stream().collect(Collectors.toMap(ScItemResponse::getOuterId, Function.identity()));
    }

    public Map<String, ScItemResponse> getScItemInfoListByIdList(List<String> idList){
        log.info("getScItemInfoList:{}",JSON.toJSON(idList));
        ScItemSearchReqAbilityDTO scItemSearchReqAbilityDTO1 = new ScItemSearchReqAbilityDTO();
        scItemSearchReqAbilityDTO1.setScItemIds(idList);
        Result<List<ScItemResponse>> listResult = mnInventoryCenterService.searchScItemFromDbList(scItemSearchReqAbilityDTO1);
        log.info("getScItemInfoList_result:{}",JSON.toJSON(listResult));
        List<ScItemResponse> scItemList = listResult.getResult();
        if(CollectionUtil.isEmpty(scItemList)){
            return new HashMap<>();
        }
        return scItemList.stream().collect(Collectors.toMap(ScItemResponse::getOuterId, Function.identity()));
    }

    /**
     * 根据仓库编码查询仓库ID
     * @param warehouseCode code
     * @return WarehouseQueryResponse
     */
    private WarehouseQueryResponse getWarehouseInfo(String warehouseCode){
        WarehouseQueryRequest warehouseQueryRequest = new WarehouseQueryRequest();
        warehouseQueryRequest.setMerchantCode("mengniu");
        warehouseQueryRequest.setCode(warehouseCode);
        log.info("getWarehouseInfo,queryWarehoseByCodeApi,request:{}", JSON.toJSON(warehouseQueryRequest));
        Result<WarehouseQueryResponse> warehouseResult = mnInventoryCenterService.queryWarehoseByCodeApi(warehouseQueryRequest);
        log.info("getWarehouseInfo,queryWarehoseByCodeApi,result:{}", JSON.toJSON(warehouseResult));
        WarehouseQueryResponse result = warehouseResult.getResult();
        return result;
    }

    /**
     * 根据仓库id查询仓库ID
     * @param warehouseId id
     * @return WarehouseQueryResponse
     */
    private WarehouseQueryResponse getWarehouseInfoById(String warehouseId){
        if(StringUtils.isBlank(warehouseId)){
            return null;
        }
        QueryWarehouseByIdApiRequest queryWarehouseByIdApiRequest = new QueryWarehouseByIdApiRequest();
        queryWarehouseByIdApiRequest.setWarehouseIds(Collections.singletonList(warehouseId));
        Result<List<WarehouseQueryResponse>> listResult = mnInventoryCenterService.queryWarehouseByIdApi(queryWarehouseByIdApiRequest);
        List<WarehouseQueryResponse> result = listResult.getResult();
        if(CollectionUtils.isNotEmpty(result)){
            return result.get(0);
        }
        return null;
    }

    @Override
    @FacadeInvoker(value = "调拨单修改")
    public Result<TransferOrderUpdateResponse> updateAllocateOrder(TransferOrderUpdateRequest transferOrderUpdateRequest) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("checkUpdateRequest");
        String message = checkUpdateAllocateApplyOrder(transferOrderUpdateRequest);
        stopWatch.stop();
        if(message != null){
            return Result.fail( "OTS-05-001-10-16-001", message);
        }

        String key = transferOrderUpdateRequest.getTransferOrderCode();

        try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(),
                "updateAllocateOrder" + key,
                5000,10000)) {
            if (!lock.lock()) {
                return Result.fail("OTS-05-001-10-16-040", "不能重复提交调拨单修改");
            }
            stopWatch.start("queryOldByCode");
            AllocateOrderDetailsQueryRequest queryRequest = new AllocateOrderDetailsQueryRequest();
            queryRequest.setCode(transferOrderUpdateRequest.getTransferOrderCode());
            queryRequest.setSearchEs(Boolean.FALSE);
            Result<AllocateOrderDetailsQueryResponse> allocateOrderDetailsResult = allocateOrderReadService.query(queryRequest);
            if (allocateOrderDetailsResult.getResult() == null) {
                return Result.fail("OTS-05-001-10-16-001", "调拨单数据不存在");
            }
            if (allocateOrderDetailsResult.getResult().getCode() == null) {
                return Result.fail("OTS-05-001-10-16-001", "调拨单数据不存在");
            }


            if (!EDITABLE_STATUS.contains(allocateOrderDetailsResult.getResult().getStatus())) {
                return Result.fail("OTS-05-001-10-16-003", "调拨单状态不合法,不能修改");
            }

            AllocateOrderDetailsQueryResponse result = allocateOrderDetailsResult.getResult();

            AllocateOrderSaveRequest allocateOrderSave = new AllocateOrderSaveRequest();
            allocateOrderSave.setCode(transferOrderUpdateRequest.getTransferOrderCode());
            allocateOrderSave.setSubmitFlag(Boolean.parseBoolean(transferOrderUpdateRequest.getSubmitFlag()));
            List<AllocateOrderScItemDetailDTO> existDetails = result.getAllocateOrderScItemDetailDTOS();
            if (CollectionUtils.isEmpty(existDetails)) {
                return Result.fail("OTS-05-001-10-16-001", "没有找到行记录");
            }

            Map<String, AllocateOrderScItemDetailDTO> detailLineNoInfoMap = existDetails.stream().collect(Collectors.toMap(
                    AllocateOrderScItemDetailDTO::getLineNo,
                    Function.identity(),
                    (v1, v2) -> v1));
            stopWatch.stop();
            // 修改人
            allocateOrderSave.setId(result.getId().toString());
            allocateOrderSave.setOperatorId(transferOrderUpdateRequest.getOperatorId());

            if (REMARK_ONLY_STATUS.contains(result.getStatus())) {
                // 待发货、部分发货只能修改订单标签list, 主单备注，行备注
                stopWatch.start("setChangedItemsRemarkOnly");

                if (CollectionUtils.isNotEmpty(transferOrderUpdateRequest.getOrderTag())) {
                    allocateOrderSave.setOrderTag(transferOrderUpdateRequest.getOrderTag());
                }
                if (StringUtils.isNotEmpty(transferOrderUpdateRequest.getHeadRemark())) {
                    allocateOrderSave.setRemark(transferOrderUpdateRequest.getHeadRemark());
                }

                // 查出所有明细，修改备注
                List<AllocateOrderScItemDetail> detailList = new ArrayList<>();
                Map<String, TransferOrderDetailRequest> requestNoDetailMap = transferOrderUpdateRequest.getTransferOrderDetailList().stream().collect(Collectors.toMap(TransferOrderDetailRequest::getDetailNo, Function.identity()));
                for (AllocateOrderScItemDetailDTO dto : result.getAllocateOrderScItemDetailDTOS()) {
                    // 不允许更新的字段，因为底层是覆盖式更新，这里需要从db记录中回写
                    AllocateOrderScItemDetail allocateOrderScItemDetail = convertDetailDTO2Detail(dto);

                    allocateOrderScItemDetail.setScItemId(dto.getGoodsId());
                    allocateOrderScItemDetail.setScItemName(dto.getTitle());
                    String remark = dto.getRemark();
                    String lineNo = dto.getLineNo();
                    if (requestNoDetailMap.get(lineNo) != null && requestNoDetailMap.get(lineNo).getLineRemark() != null) {
                        // 允许更新：行备注
                        remark = requestNoDetailMap.get(lineNo).getLineRemark();
                    }
                    allocateOrderScItemDetail.setRemark(remark);
                    detailList.add(allocateOrderScItemDetail);
                }

                allocateOrderSave.setAllocateOrderScItemDetails(detailList);
                stopWatch.stop();
            } else {
                // 草稿状态可以修改很多东西
                stopWatch.start("setChangedItemsDraft");
                WarehouseQueryResponse receiveLogic = null;
                WarehouseQueryResponse deliveryLogic = null;
                if (StringUtil.isNotEmpty(transferOrderUpdateRequest.getReceiveLogicWareCode())) {
                    receiveLogic = getWarehouseInfo(transferOrderUpdateRequest.getReceiveLogicWareCode());
                    allocateOrderSave.setReceiveWareHouseId(receiveLogic.getParentId());
                    allocateOrderSave.setReceiveAreaId(receiveLogic.getId());
                }
                if (StringUtil.isNotEmpty(transferOrderUpdateRequest.getDeliveryLogicWareCode())) {
                    deliveryLogic = getWarehouseInfo(transferOrderUpdateRequest.getDeliveryLogicWareCode());
                    allocateOrderSave.setShipAreaId(deliveryLogic.getId());
                    allocateOrderSave.setShipWareHouseId(deliveryLogic.getParentId());
                }
                stopWatch.stop();

                // 仓库校验
                stopWatch.start("checkWarehouse");
                String wareHouseMessage = CheckUtil.checkWareHouse4Update(result.getType(), receiveLogic, deliveryLogic);
                stopWatch.stop();
                if (wareHouseMessage != null) {
                    return Result.fail("OTS-05-001-10-16-006", wareHouseMessage);
                }

                // 自动创建履约单
                if (StringUtils.isNotBlank(transferOrderUpdateRequest.getAutoFulfillment())) {
                    if ("true".equals(transferOrderUpdateRequest.getAutoFulfillment())) {
                        allocateOrderSave.setAutoFulfillment(Boolean.TRUE);
                    } else if ("false".equals(transferOrderUpdateRequest.getAutoFulfillment())) {
                        allocateOrderSave.setAutoFulfillment(Boolean.FALSE);
                    } else {
                        return Result.fail("OTS-05-001-10-16-006", "是否自动创建履约单格式错误");
                    }
                }

                // 履约方式
                if (StringUtils.isNotBlank(transferOrderUpdateRequest.getFulfillmentTypeCode())) {
                    allocateOrderSave.setFulfillmentTypeCode(transferOrderUpdateRequest.getFulfillmentTypeCode());
                }

                // 订单标签
                if (CollectionUtils.isNotEmpty(transferOrderUpdateRequest.getOrderTag())) {
                    allocateOrderSave.setOrderTag(transferOrderUpdateRequest.getOrderTag());
                }

                // 履约优先级
                if (StringUtils.isNotBlank(transferOrderUpdateRequest.getPriority())) {
                    allocateOrderSave.setPriority(transferOrderUpdateRequest.getPriority());
                }

                // 生效日期
                if (StringUtils.isNotBlank(transferOrderUpdateRequest.getTakeEffectDate())) {
                    allocateOrderSave.setTakeEffectDate(transferOrderUpdateRequest.getTakeEffectDate());
                }

                // 单据日期
                if (ObjectUtil.isNotEmpty(transferOrderUpdateRequest.getOrderDate())) {
                    allocateOrderSave.setDocDate(transferOrderUpdateRequest.getOrderDate());
                }

                // 期望交货日期
                if (ObjectUtil.isNotEmpty(transferOrderUpdateRequest.getExpectedDeliveryDate())) {
                    allocateOrderSave.setExpectedDeliveryTime(transferOrderUpdateRequest.getExpectedDeliveryDate());
                }

                // 运输方式
                boolean freightYard = Lists.newArrayList(2, 3).contains(result.getShipMethod());
                if (StringUtils.isNotBlank(transferOrderUpdateRequest.getShipMethodCode())) {
                    String shipMethodCode = transferOrderUpdateRequest.getShipMethodCode();
                    allocateOrderSave.setShipMethod(shipMethodCode);

                    // 如果是铁运或者海运，需要查询收货逻辑仓库对应的货场仓信息
                    freightYard = "02".equals(shipMethodCode) || "03".equals(shipMethodCode);
                }

                if (freightYard && !AllocateOrderTypeEnum.FREIGHT_YARD_PICKUP.getType().equals(result.getType())) {
                    if (receiveLogic == null) {
                        receiveLogic = getWarehouseInfoById(result.getReceiveAreaId());
                    }

                    if (receiveLogic == null || MapUtils.isEmpty(receiveLogic.getBizFeatures()) || StringUtils.isBlank(receiveLogic.getBizFeatures().get("freightYardCode"))) {
                        return Result.fail("OTS-05-001-10-16-410", "收货逻辑仓库对应的货场仓信息不存在");
                    }
                    allocateOrderSave.setTransferWarehouseId(receiveLogic.getBizFeatures().get("freightYardCode"));
                }

                // 备注
                if (StringUtils.isNotEmpty(transferOrderUpdateRequest.getHeadRemark())) {
                    allocateOrderSave.setRemark(transferOrderUpdateRequest.getHeadRemark());
                }

                // features
                allocateOrderSave.setFeatures(getFeatures(receiveLogic, deliveryLogic, result.getFeatures(), freightYard));

                // bizFeature
                allocateOrderSave.setBizFeatures(getBizFeature(deliveryLogic, receiveLogic));

                if (CollectionUtil.isNotEmpty(transferOrderUpdateRequest.getTransferOrderDetailList())) {

                    Map<String, List<TransferOrderDetailRequest>> detailMap = new HashMap<>();
                    transferOrderUpdateRequest.getTransferOrderDetailList().forEach(detail -> {
                        if (StringUtils.isNotBlank(detail.getDetailNo())) {
                            List<TransferOrderDetailRequest> updateList = CollectionUtils.isNotEmpty(detailMap.get("update")) ? detailMap.get("update") : new ArrayList<>();
                            updateList.add(detail);
                            detailMap.put("update", updateList);
                        } else {
                            List<TransferOrderDetailRequest> createList = CollectionUtils.isNotEmpty(detailMap.get("create")) ? detailMap.get("create") : new ArrayList<>();
                            createList.add(detail);
                            detailMap.put("create", createList);
                        }
                    });

                    List<AllocateOrderScItemDetail> detailList = new ArrayList<>();

                    // 关联单及关联单行号
                    String relatedOrderCode = result.getRelatedAllocateOrderCode();
                    List<String> relatedLineNo = null;
                    if (StringUtils.isNotEmpty(relatedOrderCode)) {
                        stopWatch.start("checkRelatedOrder");
                        Result<List<AllocateOrderDetail>> listResult = allocateOrderDetailService.loadAllocateOrderDetailList(AllocateOrderDetailLoadListRequest.newAllocateOrderDetailLoadListRequestBuilder()
                                .allocateOrderCode(relatedOrderCode).build());
                        if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())) {
                            relatedLineNo = listResult.getResult().stream().map(AllocateOrderDetail::getLineNo).filter(Objects::nonNull).map(Objects::toString).distinct().collect(Collectors.toList());
                        }
                        stopWatch.stop();
                    }

                    // 处理更新的行
                    if (CollectionUtils.isNotEmpty(detailMap.get("update"))) {
                        // 处理更新的行
                        List<TransferOrderDetailRequest> updateList = detailMap.get("update");

                        List<AllocateOrderScItemDetail> updateDetailList = new ArrayList<>();
                        stopWatch.start("handleUpdateLine");
                        for (TransferOrderDetailRequest request : updateList) {

                            String detailNo = request.getDetailNo();
                            if (StringUtils.isBlank(detailNo)) {
                                return Result.fail("OTS-05-001-10-16-409", "更新的行号不能为空");
                            }
                            AllocateOrderScItemDetail allocateOrderScItemDetail = new AllocateOrderScItemDetail();
                            AllocateOrderScItemDetailDTO x = detailLineNoInfoMap.get(detailNo);
                            // 调拨单行号不匹配时报错
                            if (x == null) {
                                return Result.fail("OTS-05-001-10-16-410", "通过更新的行号没有找到行记录");
                            }
                            allocateOrderScItemDetail.setLineNo(detailNo);
                            // 允许更新：数量，单位，生产日期，行备注
                            allocateOrderScItemDetail.setQuantity(StringUtils.isNotBlank(request.getQuantity()) ? request.getQuantity() : x.getQuantity());
                            allocateOrderScItemDetail.setUnit(StringUtils.isNotBlank(request.getUnit()) ? request.getUnit() : x.getUnit());
                            allocateOrderScItemDetail.setProductDate(StringUtils.isNotBlank(request.getProductDate()) ? request.getProductDate() : x.getProductDate());
                            allocateOrderScItemDetail.setRemark(StringUtils.isNotBlank(request.getLineRemark()) ? request.getLineRemark() : x.getRemark());

                            // 不允许更新的字段，因为底层是覆盖式更新，这里需要从db记录中回写
                            allocateOrderScItemDetail.setScItemId(x.getGoodsId());
                            allocateOrderScItemDetail.setScItemName(x.getTitle());
                            allocateOrderScItemDetail.setScItemCode(x.getScItemCode());
                            allocateOrderScItemDetail.setThirdLineNo(x.getThirdLineNo());
                            allocateOrderScItemDetail.setAllocateApplyOrderLineNo(x.getAllocateApplyOrderLineNo());
                            allocateOrderScItemDetail.setRelatedAllocateSubOrderId(x.getRelatedAllocateSubOrderId());
                            allocateOrderScItemDetail.setCreator(x.getCreator());
                            updateDetailList.add(allocateOrderScItemDetail);
                        }
                        stopWatch.stop();
                        detailList.addAll(updateDetailList);
                    }

                    // 处理新增的行
                    if (CollectionUtils.isNotEmpty(detailMap.get("create"))) {
                        List<TransferOrderDetailRequest> createList = detailMap.get("create");
                        stopWatch.start("checkCreateLine");
                        for (TransferOrderDetailRequest request : createList) {
                            // check: 必填：来源单行号，物料编码，数量，单位
                            String errorMessage = checkCreateDetail(request, result, relatedLineNo);
                            if (StringUtils.isNotEmpty(errorMessage)) {
                                return Result.fail("OTS-05-001-10-16-410", errorMessage);
                            }
                        }
                        stopWatch.stop();
                        List<String> goodsCode = createList.stream().map(TransferOrderDetailRequest::getGoodsCode)
                                .filter(Objects::nonNull).collect(Collectors.toList());

                        stopWatch.start("checkCreateItem");
                        Map<String, ScItemResponse> scItemInfoMap = getScItemInfoList(goodsCode);
                        // 货品状态校验
                        String checkScItemTypeAndStatus = CheckUtil.getCheckScItemTypeAndStatus(scItemInfoMap);
                        if (checkScItemTypeAndStatus != null) {
                            return Result.fail("OTS-05-001-10-16-001", checkScItemTypeAndStatus);
                        }
                        stopWatch.stop();
                        stopWatch.start("checkCreateItemUnit");
                        //货品单位校验
                        String checkScItemMessage = CheckUtil.checkScItemTransferOrder(createList, scItemInfoMap);
                        if (checkScItemMessage != null) {
                            return Result.fail("OTS-05-001-10-16-001", checkScItemMessage);
                        }
                        stopWatch.stop();
                        // 转换
                        stopWatch.start("convertDto2Detail");
                        List<AllocateOrderScItemDetail> createDetailList = createList.stream().map(x -> {
                            ScItemResponse scItemResponse = scItemInfoMap.get(x.getGoodsCode());
                            AllocateOrderScItemDetail allocateOrderScItemDetail = new AllocateOrderScItemDetail();
                            allocateOrderScItemDetail.setScItemId(scItemResponse.getScItemId());
                            allocateOrderScItemDetail.setScItemName(scItemResponse.getTitle());
                            allocateOrderScItemDetail.setScItemCode(x.getGoodsCode());
                            allocateOrderScItemDetail.setQuantity(x.getQuantity());
                            allocateOrderScItemDetail.setUnit(x.getUnit());
                            allocateOrderScItemDetail.setRemark(x.getLineRemark());
                            if (StringUtils.isNotBlank(x.getProductDate())) {
                                allocateOrderScItemDetail.setProductDate(x.getProductDate());
                            } else {
                                allocateOrderScItemDetail.setProductDate(date2String(new Date()));
                            }
                            allocateOrderScItemDetail.setThirdLineNo(x.getOutDetailLineNo());
                            allocateOrderScItemDetail.setAllocateApplyOrderLineNo(x.getAllocateApplyOrderLineId());
                            allocateOrderScItemDetail.setRelatedAllocateSubOrderId(x.getRelatedAllocateSubOrderNo());
                            allocateOrderScItemDetail.setCreator(transferOrderUpdateRequest.getOperatorId());
                            return allocateOrderScItemDetail;
                        }).collect(Collectors.toList());

                        detailList.addAll(createDetailList);
                        stopWatch.stop();
                    }
                    allocateOrderSave.setAllocateOrderScItemDetails(detailList);
                }
            }
            // 执行修改
            stopWatch.start("doUpdate");
            Result<AllocateOrderCreateResponse> save = allocateOrderWriteService.updateSaveAllocateOrder(allocateOrderSave);
            stopWatch.stop();
            if (!save.isSuccess()) {
                return Result.fail("OTS-05-001-10-16-500", "修改失败:" + save.getMessage());
            }

            if (Boolean.parseBoolean(transferOrderUpdateRequest.getSubmitFlag()) && StringUtils.equals(AllocateOrderStatus.DRAFT.getValue().toString(), result.getStatus())){
                stopWatch.start("submitUpdate");
                submitAllocateOrder(transferOrderUpdateRequest.getTransferOrderCode());
                stopWatch.stop();
            }

            // 整理返回结果
            TransferOrderUpdateResponse response = new TransferOrderUpdateResponse();
            response.setTransferOrderCode(save.getResult().getCode());
            response.setThirdAllocateOrderCode(save.getResult().getThirdAllocateOrderId());
            List<TransferOrderCreateDetailResponse> detailResponses = new ArrayList<>();
            for (AllocateOrderDetailSDO allocateOrderDetailSDO : save.getResult().getAllocateOrderDetailList()) {
                TransferOrderCreateDetailResponse detailResponse = new TransferOrderCreateDetailResponse();
                detailResponse.setDetailNo(allocateOrderDetailSDO.getLineNo());
                String thirdLineNo = allocateOrderDetailSDO.getThirdLineNo();
                detailResponse.setOutDetailLineNo(thirdLineNo);
                detailResponses.add(detailResponse);
            }
            response.setTransferOrderCreateDetailResponseList(detailResponses);
            log.info("TransferOrderWriteService|updateAllocateOrder|cost={}",stopWatch.prettyPrint());
            return Result.success(response);
        } catch (Throwable t) {
            // log
            log.error("TransferOrderWriteService|UpdateAllocateOrder|error",t);
            return Result.fail("OTS-05-001-10-16-055","修改调拨单失败" + t.getMessage());
        }
    }

    private AllocateOrderScItemDetail convertDetailDTO2Detail(AllocateOrderScItemDetailDTO dto) {
        if (dto == null) {
            return null;
        }

        AllocateOrderScItemDetail detail = new AllocateOrderScItemDetail();

        // 手动复制所有匹配的属性
        detail.setId(dto.getId());
        detail.setLineNo(dto.getLineNo());
        detail.setAllocateApplyOrderLineNo(dto.getAllocateApplyOrderLineNo());
        detail.setScItemCode(dto.getScItemCode());
        detail.setScItemName(dto.getScItemName());
        detail.setQuantity(dto.getQuantity());
        detail.setConfirmedQuantity(dto.getConfirmQuantity());
        detail.setDeliveryQuantity(dto.getDeliveryQuantity());
        detail.setReceivedQuantity(dto.getReceiveQuantity());
        detail.setUnit(dto.getUnit());
        // 注意：下面的standardPrice没有对应的setter，因为它们类型不匹配
        // detail.setStandardPrice(dto.getStandardPrice());
        detail.setExpectedProductionDate(dto.getExpectedProductionDate());
        detail.setIsClosed(dto.getClosed());
        detail.setClosedReason(dto.getClosedReason());
        detail.setStatus(dto.getStatus());
        detail.setPrice(dto.getPrice());
        detail.setApplyQuantity(dto.getApplyQuantity());
        detail.setGoodsId(dto.getGoodsId());
        detail.setScItemId(dto.getScItemId());
        detail.setTitle(dto.getTitle());
        detail.setRemark(dto.getRemark());
        detail.setProductDate(dto.getProductDate());
        // 注意：下面的unitPrice没有对应的setter，因为它们类型不匹配
        // detail.setUnitPrice(dto.getUnitPrice());
        detail.setThirdLineNo(dto.getThirdLineNo());
        detail.setRelatedAllocateSubOrderId(dto.getRelatedAllocateSubOrderId());
        detail.setCreator(dto.getCreator());

        return detail;
    }


    private String checkCreateDetail(TransferOrderDetailRequest request, AllocateOrderDetailsQueryResponse allocateOrder, List<String> detailNoList) {

        if (StringUtils.isBlank(request.getOutDetailLineNo())) {
            return "新增行外部单号不能为空";
        }
        if (StringUtils.isBlank(request.getGoodsCode())) {
           return  "新增行物料编码不能为空";
        }
        if (StringUtils.isBlank(request.getQuantity())) {
            return "新增行数量不能为空";
        }
        if (StringUtils.isBlank(request.getUnit())) {
            return "新增行单位不能为空";
        }

        // 关联单行号：当调拨单类型为货场提货单时必传，其他类型如果传了也要校验是否存在
        if (AllocateOrderTypeEnum.FREIGHT_YARD_PICKUP.getType().equals(allocateOrder.getType())) {
            if (StringUtils.isBlank(request.getRelatedAllocateSubOrderNo())) {
                return "货场提货单关联单行号不能为空";
            }
            if (CollectionUtils.isEmpty(detailNoList) || !detailNoList.contains(request.getRelatedAllocateSubOrderNo())) {
                return  "关联单行号不存在";
            }
        } else if (StringUtils.isNotEmpty(request.getRelatedAllocateSubOrderNo())) {
            if (CollectionUtils.isEmpty(detailNoList) || !detailNoList.contains(request.getRelatedAllocateSubOrderNo())) {
                return  "关联单行号不存在";
            }
        }

        // 预报单行号
        if (StringUtils.isNotBlank(allocateOrder.getAllocateApplyOrderCode())) {
            if (StringUtils.isBlank(request.getAllocateApplyOrderLineId())) {
                return  "该调拨单关联了预报单，新增行时预报单行号不能为空";
            }
        }


        return null;
    }

    private String checkUpdateAllocateApplyOrder(TransferOrderUpdateRequest transferOrderUpdateRequest){
        if (StrUtil.isBlank(transferOrderUpdateRequest.getFromSys())){
            return "来源系统不能为空";
        }
        if (transferOrderUpdateRequest.getFromSys().length()>16){
            return "来源系统长度不能超过16";
        }
        if (!checkDictionary(FROM_SYS_GROUP,transferOrderUpdateRequest.getFromSys())){
            return "来源系统非法";
        }
        if (StrUtil.isBlank(transferOrderUpdateRequest.getBusinessType())){
            return "业态不能为空";
        }
        if (transferOrderUpdateRequest.getBusinessType().length()>16){
            return "业态长度不能超过16";
        }
        if (!checkDictionary(BUSINESS_TYPE_GROUP,transferOrderUpdateRequest.getBusinessType())){
            return "业态非法";
        }
        if (StrUtil.isBlank(transferOrderUpdateRequest.getSubmitFlag())){
            return "是否提交不能为空";
        }
        if (transferOrderUpdateRequest.getSubmitFlag().length()>5){
            return "是否提交长度不能超过5";
        }
        if (!transferOrderUpdateRequest.getSubmitFlag().matches("^true|false$")){
            return "是否提交格式非法";
        }
        if (StrUtil.isBlank(transferOrderUpdateRequest.getTransferOrderCode())){
            return "调拨单号不能为空";
        }
        if (transferOrderUpdateRequest.getTransferOrderCode().length()>32){
            return "调拨单号长度不能超过32";
        }

        if (StrUtil.isNotBlank(transferOrderUpdateRequest.getReceiveLogicWareCode())
                &&transferOrderUpdateRequest.getReceiveLogicWareCode().length()>32){
            return "收货逻辑仓库编码长度不能超过32";
        }
        if (StrUtil.isNotBlank(transferOrderUpdateRequest.getDeliveryLogicWareCode())
                &&transferOrderUpdateRequest.getDeliveryLogicWareCode().length()>32){
            return "发货逻辑仓库编码长度不能超过32";
        }

        if (StringUtils.isNotBlank(transferOrderUpdateRequest.getAutoFulfillment())) {
            if (transferOrderUpdateRequest.getAutoFulfillment().length() > 5) {
                return  "是否自动创建履约单长度不能超过5";
            }
            if (!transferOrderUpdateRequest.getSubmitFlag().matches("^true|false$")){
                return "是否自动创建履约单格式非法";
            }
        }

        if (StringUtils.isNotEmpty(transferOrderUpdateRequest.getFulfillmentTypeCode())) {
            if (transferOrderUpdateRequest.getFulfillmentTypeCode().length() > 4) {
                return "履约方式长度不能超过4";
            }
            if (!checkDictionary(FULFILLMENT_TYPE,transferOrderUpdateRequest.getFulfillmentTypeCode())) {
                return "履约方式非法";
            }
        }

        List<String> orderTag = transferOrderUpdateRequest.getOrderTag();
        if (CollectionUtils.isNotEmpty(orderTag)) {
            if (orderTag.size() > 10) {
                return "订单标签列表数量不能大于10";
            }
            for (String tag : orderTag) {
                if (tag.length() > 32) {
                    return "订单标签长度不能大于32";
                }
            }
            List<String> collect1 = orderTag.stream().map(String::trim).distinct().collect(Collectors.toList());
            if (collect1.size() != orderTag.size()) {
                return "订单标签不能重复";
            }
            List<String> finalList = new ArrayList<>();
            for (String tag : collect1) {
                tag = tag.trim();
                if (!checkDictionary(ALLOCATE_ORDER_TAG, tag)){
                    return "订单标签不合法";
                }
                finalList.add(tag);
            }
            List<String> tagList = finalList.stream().distinct().collect(Collectors.toList());

            transferOrderUpdateRequest.setOrderTag(tagList);
        }

        if (StringUtils.isNotBlank(transferOrderUpdateRequest.getPriority())) {
            if (transferOrderUpdateRequest.getPriority().length() > 4) {
                return "履约优先级长度不能大于4";
            }
            ArrayList<String> legalList = Lists.newArrayList("1", "100");
            if (!legalList.contains(transferOrderUpdateRequest.getPriority())) {
                return "履约优先级非法";
            }
        }

        if (StringUtils.isNotBlank(transferOrderUpdateRequest.getTakeEffectDate())) {
            if (transferOrderUpdateRequest.getTakeEffectDate().length() != 10) {
                return "生效日期长度不能大于或小于10";
            }
            if (!CheckUtil.isLegalDateNew(transferOrderUpdateRequest.getTakeEffectDate())) {
                return "生效日期格式错误";
            }
        }

        String operatorId = transferOrderUpdateRequest.getOperatorId();
        if (StringUtils.isBlank(operatorId)) {
            return "修改人不能为空";
        }

        if (operatorId.length() > 32) {
            return "修改人长度不能大于32";
        }

        if (StrUtil.isNotBlank(transferOrderUpdateRequest.getOrderDate())){
            if (transferOrderUpdateRequest.getOrderDate().length() != 10){
                return "单据日期长度不能超过10也不能小于10";
            }
            if (!CheckUtil.isLegalDateNew(transferOrderUpdateRequest.getOrderDate())){
                return "单据日期格式错误";
            }
        }

        String expectedDeliveryDate = transferOrderUpdateRequest.getExpectedDeliveryDate();
        if (StrUtil.isNotBlank(expectedDeliveryDate)){
            if (expectedDeliveryDate.length() != 10){
                return "期望交货日期长度不能超过10也不能小于10";
            }
            if (!CheckUtil.isLegalDateNew(expectedDeliveryDate)){
                return "期望交货日期格式错误";
            }
        }

        String shipMethodCode = transferOrderUpdateRequest.getShipMethodCode();
        if (StringUtils.isNotBlank(shipMethodCode)) {
            if(shipMethodCode.length() > 32){
                return "运输方式字段长度不能大于32";
            }
            if (!checkDictionary("shipMethod", shipMethodCode)) {
                return "运输方式不合法";
            }
        }

        if (StrUtil.isNotBlank(transferOrderUpdateRequest.getHeadRemark())
                &&transferOrderUpdateRequest.getHeadRemark().length()>200){
            return "抬头备注长度不能超过200";
        }

        if(CollectionUtil.isEmpty(transferOrderUpdateRequest.getTransferOrderDetailList())){
            return "明细信息必传，若期望整单删除，请调用调拨单取消API";
        }

        if (transferOrderUpdateRequest.getTransferOrderDetailList().size() > 100) {
            return "子单数量不能超过100";
        }

        for(TransferOrderDetailRequest x :transferOrderUpdateRequest.getTransferOrderDetailList()) {

            trimStrings(x);

            if (areAllFieldsNullOrEmpty(x)) {
                return "明细信息必传，若期望整单删除，请调用调拨单取消API";
            }

            if (StringUtils.isNotBlank(x.getDetailNo())) {
                if (x.getDetailNo().length() > 32) {
                    return "调拨单行号长度不能大于32";
                }
            }


            if(StringUtils.isNotBlank(x.getOutDetailLineNo())){
                if(x.getOutDetailLineNo().length() >32){
                    return "外部行号段长度不能大于32";
                }
            }

            if (StringUtils.isNotBlank(x.getRelatedAllocateSubOrderNo())) {
                if (x.getRelatedAllocateSubOrderNo().length() > 32) {
                    return "关联单行号长度不能大于32";
                }
            }

            if (StringUtils.isNotEmpty(x.getAllocateApplyOrderLineId())) {
                if (x.getAllocateApplyOrderLineId().length() > 32) {
                    return "预报单行号长度不能大于32";
                }
            }

            if(StringUtils.isNotBlank(x.getGoodsCode())){
                if(x.getGoodsCode().length() >32){
                    return "物料编码字段长度不能大于32";
                }
            }

            if(StringUtils.isNotBlank(x.getQuantity())){
                if(!StringUtils.isNumeric(x.getQuantity())){
                    return "数量输入非法";
                }
                if (Long.parseLong(x.getQuantity()) > Integer.MAX_VALUE) {
                    return "物料数量不能大于2147483647";
                }
                if (Long.parseLong(x.getQuantity()) < 1) {
                    return "物料数量不能小于等于0";
                }
            }

            if(StringUtils.isNotBlank(x.getUnit())) {
                if(x.getUnit().length() > 32){
                    return "单位字段长度不能大于32";
                }
            }


            if (StringUtils.isNotEmpty(x.getProductDate())){
                if(x.getProductDate().length() != 10){
                    return "物料生产日期长度不能大于10或小于10";
                }
                if(!CheckUtil.isLegalDateNew(x.getProductDate())){
                    return "物料生产日期格式错误";
                }
            }

            if (StringUtils.isNotBlank(x.getLineRemark())) {
                if (x.getLineRemark().length() > 200) {
                    return "行备注的长度不能超过200";
                }
            }

        }

        return null;
    }

    private boolean areAllFieldsNullOrEmpty(Object object) {
        if (object == null) {
            return true;
        }

        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            // You might want to set accessible to true if you can't access private fields
            field.setAccessible(true);
            Object value = null;
            try {
                value = field.get(object);
            } catch (IllegalAccessException e) {
                // ignore
            }
            if (value != null) {
                if (value instanceof Long) {
                    continue;
                }
                if (value instanceof String && !((String) value).isEmpty()) {
                    return false;
                } else if (!(value instanceof String)) {
                    // The current field is not a String, thus not null or empty
                    return false;
                }
            }
        }
        return true;
    }

    private void trimStrings(Object obj) {
        if (obj == null) {
            return;
        }

        // 获取obj对象的类对象
        Class<?> clazz = obj.getClass();

        // 遍历所有字段
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            // 如果字段是String类型的
            if (field.getType().equals(String.class)) {
                field.setAccessible(true); // 设置私有字段可以被访问
                try {
                    // 获取字段的值
                    String value = (String) field.get(obj);
                    if (value != null) {
                        // 对字符串进行trim()操作
                        value = value.trim();

                        // 将trim后的值重新赋给字段
                        field.set(obj, value);
                    }
                } catch (IllegalAccessException e) {
                    // ignore
                }
            }
        }
    }

    @Override
    @FacadeInvoker(value = "调拨单关闭")
    public Result<TransferOrderCloseResponse> closeAllocateOrder(TransferOrderCloseRequest transferOrderCloseRequest) {
        String errorMessage = checkTransferOrderCloseRequest(transferOrderCloseRequest);
        if (StringUtils.isNotEmpty(errorMessage)) {
            return Result.fail( "OTS-05-001-10-16-001", errorMessage);
        }

        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|enter|request={}", JSON.toJSONString(transferOrderCloseRequest));

        List<TransferOrderCloseDetail> closeList = transferOrderCloseRequest.getCloseList();

        // 去重
        List<TransferOrderCloseDetail> filteredList = new ArrayList<>(closeList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        detail -> detail.getTransferOrderCode() + "@" + detail.getDetailNo(),
                        Function.identity(),
                        (v1, v2) -> v1))
                .values());

        if (filteredList.size() != closeList.size()) {
            return Result.fail( "OTS-05-001-10-16-001", "关闭列表明细不能重复");
        }
        // 批量查询
        List<String> allocateOrderCodeList = filteredList.stream().map(TransferOrderCloseDetail::getTransferOrderCode).filter(Objects::nonNull).distinct().collect(Collectors.toList());

        // 主单
        Result<List<AllocateOrder>> orderListResult = allocateOrderService.batchQueryByCodeList(BatchQueryByCodeListRequest.builder().codeList(allocateOrderCodeList).build());
        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|queryAllocateOrder|code={}|result={}",JSON.toJSONString(allocateOrderCodeList), JSON.toJSONString(orderListResult));
        List<AllocateOrder> orderList = orderListResult.getResult();
        if (CollectionUtils.isEmpty(orderList)) {
            filteredList.forEach(detail -> {
                detail.setSuccess(Boolean.FALSE);
                detail.setErrorCode("OTS-05-001-10-17-001");
                detail.setErrorMessage("该调拨单不存在");
            });
            TransferOrderCloseResponse response = new TransferOrderCloseResponse(filteredList);
            return Result.success(response);
        }

        Map<String, AllocateOrder> orderCodeMap = orderList.stream().filter(Objects::nonNull)
                .collect(Collectors.toMap(AllocateOrder::getCode, Function.identity(), (v1, v2) -> v1));
        log.info("TransferOrderWriteServiceImpl_closeAllocateOrder_orderCodeMap:{}",JSON.toJSONString(orderCodeMap));
        // 子单，根据主单号分组
        Result<List<AllocateOrderDetail>> detailListResult = allocateOrderDetailService.batchQueryDetailByAllocateOrderCodeList(BatchQueryDetailByAllocateOrderCodeListRequest
                .builder().allocateOrderCodeList(allocateOrderCodeList).build());
        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|queryAllocateDetail|code={}|result={}",JSON.toJSONString(allocateOrderCodeList), JSON.toJSONString(detailListResult));
        List<AllocateOrderDetail> details = detailListResult.getResult();
        if (CollectionUtils.isEmpty(details)) {
            filteredList.forEach(detail -> {
                detail.setSuccess(Boolean.FALSE);
                detail.setErrorCode("OTS-05-001-10-17-001");
                detail.setErrorMessage("该调拨单不存在该行");
            });
        }
        // key: 主单号，value: key: 行号，value: 子单
        Map<String, Map<String, AllocateOrderDetail>> detailMap = details.stream()
                .collect(Collectors.groupingBy(
                        AllocateOrderDetail::getAllocateOrderCode,
                        Collectors.toMap(
                                detail -> detail.getLineNo().toString(),
                                detail -> detail
                        )
                ));

        // 履约单，需要先从调拨单的feature上取
        List<String> forwardFulfillmentNoList = orderList.stream().filter(Objects::nonNull).map(AllocateOrder::getFeatures).filter(StringUtils::isNotBlank)
                .distinct().map(FeatureUtil::fromString).filter(MapUtils::isNotEmpty).map(feature -> feature.get("forwardFulfillmentOrderNo"))
                .filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());

        // 批量查询履约单
        Map<String, FulfillmentGetRes> fulfillmentNoMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(forwardFulfillmentNoList)) {
            BatchGetReq batchGetReq = new BatchGetReq();
            batchGetReq.setFulfillmentOrderNoList(forwardFulfillmentNoList);
            // batchGetReq.setFulfillmentDirectionType(FulfillmentDirectionTypeEnum.FORWARD.getValue());
            com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result<List<FulfillmentGetRes>> fulfillmentResult = fulfillmentOrderAbilityService.batchGet(batchGetReq);
            log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|queryFulfillment|request={}|result={}",JSON.toJSONString(batchGetReq), JSON.toJSONString(fulfillmentResult));
            if (CollectionUtils.isNotEmpty(fulfillmentResult.getResult())) {
                fulfillmentNoMap = fulfillmentResult.getResult().stream().filter(Objects::nonNull)
                        .collect(Collectors.toMap(FulfillmentGetRes::getFulfillmentOrderNo, Function.identity()));
            }
        }

        List<TransferOrderCloseDetail> resultList = new ArrayList<>();
        List<TransferOrderCloseDetail> toCloseList = new ArrayList<>();
        for (TransferOrderCloseDetail transferOrderCloseDetail : filteredList) {
            String transferOrderCode = transferOrderCloseDetail.getTransferOrderCode();
            String detailNo = transferOrderCloseDetail.getDetailNo();

            AllocateOrder allocateOrder = orderCodeMap.get(transferOrderCode);

            if (allocateOrder == null) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-001");
                transferOrderCloseDetail.setErrorMessage("该调拨单不存在");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            //【判断一：履约方式】履约方式为大仓发货，大仓收货，虚拟移库之一，其他履约方式代表由SAP发起后并同步中台，需在SAP中操作关闭后通过集成接口同步中台。
            if (!FulfillmentTypeEnum.PILOT2PILOT.getValue().toString().equals(allocateOrder.getFulfillmentTypeCode())
                    && !FulfillmentTypeEnum.VIRTUAL_TRANSFER.getValue().toString().equals(allocateOrder.getFulfillmentTypeCode())) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-002");
                transferOrderCloseDetail.setErrorMessage("履约方式为大仓发货大仓收货，虚拟移库才可以关闭调拨单");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            // 【判断二：调拨子单状态】子单状态为待发货,部分发货，未收货部分发货，部分收货部分发货，货场仓未收货部分发货，货场部分收货之一才允许关闭。
            Map<String, AllocateOrderDetail> detailLineMap = detailMap.get(transferOrderCode);
            if (MapUtils.isEmpty(detailLineMap)) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-001");
                transferOrderCloseDetail.setErrorMessage("该调拨单不存在");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            AllocateOrderDetail allocateOrderDetail = detailLineMap.get(detailNo);

            if (allocateOrderDetail == null) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-001");
                transferOrderCloseDetail.setErrorMessage("该调拨单不存在这一行");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            if (!CLOSEABLE_STATUS.contains(allocateOrderDetail.getStatus())) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-003");
                transferOrderCloseDetail.setErrorMessage("调拨子单状态非法");
                resultList.add(transferOrderCloseDetail);
                continue;
            }
            transferOrderCloseDetail.setDetailId(allocateOrderDetail.getId());
            transferOrderCloseDetail.setStatus(allocateOrderDetail.getStatus());

            // 【判断三：关联的履约子单状态】根据【调拨单号+行号】查询所关联的【正向履约单明细行】
            //      a. 若查询不到，则允许关闭。
            String bizFeatures = allocateOrder.getFeatures();
            Map<String, String> featureMap = FeatureUtil.fromString(bizFeatures);
            if (MapUtils.isEmpty(featureMap) || StringUtils.isEmpty(featureMap.get("forwardFulfillmentOrderNo"))) {
                toCloseList.add(transferOrderCloseDetail);
                continue;
            }

            String fulfillmentOrderCode = featureMap.get("forwardFulfillmentOrderNo");

            FulfillmentGetRes fulfillmentRes = fulfillmentNoMap.get(fulfillmentOrderCode);
            if (fulfillmentRes == null) {
                toCloseList.add(transferOrderCloseDetail);
                continue;
            }

            // 能查询到履约单和子单
            List<FulfillmentDetailGetRes> detailList = fulfillmentRes.getDetailList();
            if (CollectionUtils.isEmpty(detailList)) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-006");
                transferOrderCloseDetail.setErrorMessage("履约单没有明细行");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            Map<String, FulfillmentDetailGetRes> fulfillmentOrderDetailMap = detailList.stream().collect(Collectors.toMap(FulfillmentDetailGetRes::getRefOrderLineNo, Function.identity(), (v1, v2) -> v1));
            FulfillmentDetailGetRes fulfillmentOrderDetail = fulfillmentOrderDetailMap.get(detailNo);
            // b. 若能查询到，且所查询到的所有正向履约单明细行的状态都为【已取消】或【已完成】时，且累加的【已出库数量】小于【调拨单数量】

            if (fulfillmentOrderDetail != null) {
                // 7: 已取消，8:已完成
                List<String> allowedStatus = Lists.newArrayList("7", "8");
                if (!allowedStatus.contains(fulfillmentOrderDetail.getStatus())) {
                    transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                    transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-006");
                    transferOrderCloseDetail.setErrorMessage("履约单明细行的状态不是已取消或已完成");
                    resultList.add(transferOrderCloseDetail);
                    continue;
                }
                Integer shipQuantity = allocateOrderDetail.getShipQuantity();
                String quantity = allocateOrderDetail.getQuantity();
                if (StringUtils.isEmpty(quantity)) {
                    transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                    transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-006");
                    transferOrderCloseDetail.setErrorMessage("调拨单行上的数量为空");
                    resultList.add(transferOrderCloseDetail);
                    continue;
                }
                if (shipQuantity != null) {
                    BigDecimal allocateOrderQuantity = new BigDecimal(quantity);
                    BigDecimal shippedQuantity = new BigDecimal(shipQuantity);
                    int compare = shippedQuantity.compareTo(allocateOrderQuantity);
                    if (compare >= 0) {
                        transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                        transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-007");
                        transferOrderCloseDetail.setErrorMessage("无法关闭，已出库数量不小于调拨单数量");
                        resultList.add(transferOrderCloseDetail);
                        continue;
                    }
                }
                // 已发货数量等于已收货数量，调拨单明细状态应推进到已完成或已发货，货场仓已收货
                Integer receiveQuantity = allocateOrderDetail.getReceiveQuantity();
                if (shipQuantity != null && receiveQuantity != null) {
                    BigDecimal receiveQuantityNum = new BigDecimal(receiveQuantity);
                    BigDecimal shippedQuantity = new BigDecimal(shipQuantity);
                    if (shippedQuantity.compareTo(receiveQuantityNum) == 0) {
                        Integer originStatus = transferOrderCloseDetail.getStatus();
                        transferOrderCloseDetail.setStatus(originStatus + UnifiedInventoryKey.PART_RECEIVE_2_COMPLETE_VALUE);
                    }
                }

            }
            toCloseList.add(transferOrderCloseDetail);
        }

        // 取消
        AllocateOrderCloseRequest request = new AllocateOrderCloseRequest();
        String operatorId = transferOrderCloseRequest.getOperatorId();
        request.setOperatorId(operatorId);
        log.info("TransferOrderWriteServiceImpl_closeAllocateOrder_toCloseList:{}",JSON.toJSONString(toCloseList));
        request.setCloseList(toCloseList.stream().map(detail -> {
            AllocateOrderCloseDTO dto = new AllocateOrderCloseDTO();
            BeanUtils.copyProperties(detail, dto);
            dto.setOperatorId(operatorId);
            AllocateOrder allocateOrder = orderCodeMap.get(detail.getTransferOrderCode());
            if (allocateOrder == null) {
                return dto;
            }
            dto.setOutAllocateOrderId(allocateOrder.getOutAllocateOrderId());
            Map<String, AllocateOrderDetail> stringAllocateOrderDetailMap = detailMap.get(detail.getTransferOrderCode());
            if (MapUtils.isEmpty(stringAllocateOrderDetailMap)) {
                return dto;
            }
            AllocateOrderDetail allocateOrderDetail = stringAllocateOrderDetailMap.get(detail.getDetailNo());
            if (allocateOrderDetail == null) {
                return dto;
            }
            dto.setOutAllocateOrderLineNo(allocateOrderDetail.getOutAllocateOrderLineId());
            return dto;
        }).collect(Collectors.toList()));
        AllocateOrderCloseResponse closeResponse = allocateOrderWriteService.closeAllocateOrder(request);
        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|close|request={}|response={}", JSON.toJSONString(request), JSON.toJSONString(closeResponse));

        if (CollectionUtils.isNotEmpty(closeResponse.getResultList())) {
            resultList.addAll(closeResponse.getResultList().stream().map(dto -> {
                TransferOrderCloseDetail detail = new TransferOrderCloseDetail();
                detail.setErrorCode(dto.getErrorCode());
                detail.setErrorMessage(dto.getErrorMessage());
                detail.setTransferOrderCode(dto.getTransferOrderCode());
                detail.setDetailNo(dto.getDetailNo());
                detail.setSuccess(dto.getSuccess());
                return detail;
            }).collect(Collectors.toList()));
        }

        // 异步校验是否需要修改主单状态
        Set<TransferOrderCloseDetail> closedSet = resultList.stream().filter(Objects::nonNull).filter(detail -> Boolean.TRUE.equals(detail.getSuccess())).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(closedSet)) {
            for (TransferOrderCloseDetail detail : closedSet) {
                ThreadPoolUtil.execute(() -> {
                    try {
                        checkAndPushAllocateOrderStatus(detail, operatorId);
                    } catch (Throwable t) {
                        log.error("TransferOrderWriteService|closeAllocateOrder|checkAndPushAllocateOrderStatus|error|resultList={}",resultList, t);
                    }
                });
            }
        }

        resultList.forEach(result -> {
            result.setDetailId(null);
            result.setStatus(null);
            result.setCloseCode(null);
        });

        TransferOrderCloseResponse response = new TransferOrderCloseResponse(resultList);
        return Result.success(response);

    }

    private void checkAndPushAllocateOrderStatus(TransferOrderCloseDetail closeDetail, String operatorId) {
        if (closeDetail == null) {
            return;
        }


        AllocateOrderDetailLoadListRequest queryRequest = AllocateOrderDetailLoadListRequest.newAllocateOrderDetailLoadListRequestBuilder().allocateOrderCode(closeDetail.getTransferOrderCode()).build();
        queryRequest.setSize(1000);
        Result<List<AllocateOrderDetail>> detailListResult = allocateOrderDetailService.loadAllocateOrderDetailList(queryRequest);
        if (CollectionUtils.isEmpty(detailListResult.getResult())) {
            return;
        }

        List<AllocateOrderDetail> detailList = detailListResult.getResult();
        // 计算主单状态
        Integer mainOrderStatus = calculateMainOrderStatus(detailList);

        AllocateOrderLoadListRequest queryOrderRequest = AllocateOrderLoadListRequest.newAllocateOrderLoadListRequestBuilder().code(closeDetail.getTransferOrderCode()).build();
        Result<List<AllocateOrder>> listResult = allocateOrderService.loadAllocateOrderList(queryOrderRequest);
        AllocateOrder allocateOrder = listResult.getResult().get(0);
        if (allocateOrder == null) {
            return;
        }
        if (mainOrderStatus != null && !Objects.equals(allocateOrder.getStatus(), mainOrderStatus)) {
            allocateOrder.setStatus(mainOrderStatus);
            allocateOrder.setOperatorId(operatorId);
            allocateOrderService.updateAllocateOrder(allocateOrder);
        }

    }

    private Integer calculateMainOrderStatus(List<AllocateOrderDetail> subOrders) {
        // 检查子单是否全部为已取消
        if (allSubOrdersHaveStatus(subOrders, AllocateOrderStatus.Cancel.getValue())) {
            return AllocateOrderStatus.Cancel.getValue();
        }

        subOrders.removeAll(subOrders.stream().filter(subOrder -> AllocateOrderStatus.Cancel.getValue().equals(subOrder.getStatus())).collect(Collectors.toList()));

        if (subOrders.size() == 1) {
            return subOrders.get(0).getStatus();
        }

        // 检查子单是否全部为已完成
        if (allSubOrdersHaveStatus(subOrders, AllocateOrderStatus.COMPLETED.getValue())) {
            return AllocateOrderStatus.COMPLETED.getValue();
        }

        // 检查子单是否包含部分发货状态
        boolean containsPartialShipment = subOrders.stream().anyMatch(detail ->
                detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue()) ||
                        detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue()) ||
                        detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue()) ||
                        detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue())
        );

        // 根据子单状态计算主单状态
        if (containsPartialShipment) {
            // 判断是否包含"货场仓"
            boolean containsYard = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue())
            );

            // 判断是否包含"部分收货"
            boolean containsPartReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue())
            );

            // 根据是否包含"货场仓"和"部分收货"返回相应状态
            if (containsYard) {
                return containsPartReceived ? AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue() :
                        AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue();
            } else {
                return containsPartReceived ? AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue() :
                        AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue();
            }
        }

        // 检查子单是否包含已发货状态且不包含部分发货状态
        boolean containsShipmentWithoutPartial = subOrders.stream().anyMatch(detail ->
                        detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_NONE_RECEIVED.getValue())
                                || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_RECEIVED.getValue())
                                || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue())
                                || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue())
                                || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue())
                                || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue())
                );

        if (containsShipmentWithoutPartial) {
            // 判断是否包含"货场仓"
            boolean containsYard = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue()) ||
                                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue())
            );

            // 判断是否包含"部分收货"
            boolean containsPartReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue())
            );

            boolean containsPartFinalFinished = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue()));

            boolean containsYardReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue()));


            boolean containsYardNoneReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue()));
            // 根据是否包含"货场仓"和"部分收货"返回相应状态
            if (containsYard) {
                if (containsPartReceived) {
                    return AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue();
                } else if (containsPartFinalFinished) {
                    return AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue();
                } else if (containsYardReceived) {
                    return AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue();
                } else if (containsYardNoneReceived) {
                    return AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue();
                }
            } else {
                return containsPartReceived ? AllocateOrderStatus.ALL_SHIPPED_PART_RECEIVED.getValue() :
                        AllocateOrderStatus.ALL_SHIPPED_NONE_RECEIVED.getValue();
            }
        }

        // 默认情况
        return null;
    }

    private boolean allSubOrdersHaveStatus(List<AllocateOrderDetail> subOrders, Integer status) {
        return subOrders.stream().allMatch(detail -> detail.getStatus().equals(status));
    }

    private String checkTransferOrderCloseRequest(TransferOrderCloseRequest transferOrderCloseRequest) {
        if (StrUtil.isBlank(transferOrderCloseRequest.getFromSys())){
            return "来源系统不能为空";
        }
        if (transferOrderCloseRequest.getFromSys().length()>16){
            return "来源系统长度不能超过16";
        }
        if (!checkDictionary(FROM_SYS_GROUP,transferOrderCloseRequest.getFromSys())){
            return "来源系统非法";
        }
        if (StrUtil.isBlank(transferOrderCloseRequest.getBusinessType())){
            return "业态不能为空";
        }
        if (transferOrderCloseRequest.getBusinessType().length()>16){
            return "业态长度不能超过16";
        }
        if (!checkDictionary(BUSINESS_TYPE_GROUP,transferOrderCloseRequest.getBusinessType())){
            return "业态非法";
        }
        if (StringUtils.isBlank(transferOrderCloseRequest.getOperatorId())) {
            return "修改人不能为空";
        }
        if (transferOrderCloseRequest.getOperatorId().length() > 32) {
            return "修改人长度不能超过32";
        }
        List<TransferOrderCloseDetail> closeList = transferOrderCloseRequest.getCloseList();
        if (CollectionUtils.isEmpty(closeList)) {
            return "关闭列表不能为空";
        }
        if (closeList.size() > 100) {
            return "关闭列表的元素数量不能超过100";
        }
        for (TransferOrderCloseDetail detail : closeList) {
            if (StringUtils.isBlank(detail.getTransferOrderCode())) {
                return "调拨单号不能为空";
            }
            if (detail.getTransferOrderCode().length() > 32) {
                return "调拨单号长度不能超过32";
            }
            if (StringUtils.isBlank(detail.getDetailNo())) {
                return "调拨单行号不能为空";
            }
            if (detail.getDetailNo().length() > 32) {
                return "调拨单行号长度不能超过32";
            }
            if (StringUtils.isNotBlank(detail.getCloseCode())) {
                String closeCode = detail.getCloseCode();
                if (closeCode.length() > 32) {
                    return "关闭原因编码长度不能超过32";
                }
            }
        }

        List<String> closeCodeList = closeList.stream().map(TransferOrderCloseDetail::getCloseCode).filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(closeCodeList)) {
            for (String closeCode : closeCodeList) {
                if (!checkDictionary(CLOSE_REASON,closeCode)) {
                    return "关闭原因编码不合法";
                }
            }
        }

        return null;
    }


    /**
     * 更新bizFeatures 这段是更新数量和 状态
     */
    @Override
    @FacadeInvoker
    public Result<Void> updateFeatures(FeaturesUpdateRequest featuresUpdateRequest) {
        log.info("transferOrderWriteService_updateFeatures_request:{}",JSON.toJSONString(featuresUpdateRequest));
        //更新主单
        if (StringUtils.isNotBlank(featuresUpdateRequest.getMainOrderCode())){
            //查询主单
//            LoadAllocateOrderRequest loadAllocateOrderRequest = LoadAllocateOrderRequest.builder().id(featuresUpdateRequest.getMainOrderId()).build();
            AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
            allocateOrderLoadListRequest.setCode(featuresUpdateRequest.getMainOrderCode());
            Result<List<AllocateOrder>> allocateOrderList = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
            if (allocateOrderList == null || CollectionUtils.isEmpty(allocateOrderList.getResult())){
                throw new FacadeException("OTS-03-005-00-15-068");
            }
            AllocateOrder allocateOrder = allocateOrderList.getResult().get(0);
            Map<String, String> mainBizFeaturesToUpdate = MapUtils.emptyIfNull(featuresUpdateRequest.getMainBizFeaturesToUpdate());
            Map<String, String> mainBizFeaturesToDelete = MapUtils.emptyIfNull(featuresUpdateRequest.getMainBizFeaturesToDelete());
            if (MapUtils.isNotEmpty(mainBizFeaturesToUpdate) || MapUtils.isNotEmpty(mainBizFeaturesToDelete)){
                //更新的参数
                Map<String, String> bizFeatures = FeatureUtil.fromString(allocateOrder.getBizFeatures());
                if (MapUtils.isNotEmpty(mainBizFeaturesToUpdate)){
                    bizFeatures.putAll(mainBizFeaturesToUpdate);
                }
                if (MapUtils.isNotEmpty(mainBizFeaturesToDelete)){
                    mainBizFeaturesToDelete.keySet().forEach(bizFeatures::remove);
                }
                UpdateFeaturesRequest updateFeaturesRequest = UpdateFeaturesRequest.builder()
                        .mainOrderCode(allocateOrder.getCode())
                        .bizFeatures(FeatureUtil.toString(bizFeatures)).build();
                log.info("updateFeatures_request:{}",JSON.toJSONString(updateFeaturesRequest));
                allocateOrderService.updateFeatures(updateFeaturesRequest);
            }
        }
        //更新子单
        Map<String, SubFeaturesRequest> subBizFeaturesMapUpdate = MapUtils.emptyIfNull(featuresUpdateRequest.getSubBizFeaturesToUpdate());
        Map<String, SubFeaturesRequest> subBizFeaturesMapDelete = MapUtils.emptyIfNull(featuresUpdateRequest.getSubBizFeaturesToDelete());

        boolean subNeedUpdateOrDelete = MapUtils.isNotEmpty(subBizFeaturesMapUpdate) || MapUtils.isNotEmpty(subBizFeaturesMapDelete);
        if (subNeedUpdateOrDelete){
            //针对同一个子单
            //获取到子单行id
            Set<String> subIdSet = Stream.concat(subBizFeaturesMapUpdate.keySet().stream(), subBizFeaturesMapDelete.keySet().stream()).collect(Collectors.toSet());
            subIdSet.forEach(subId -> {
//                LoadAllocateOrderDetailRequest loadAllocateOrderDetailRequest = LoadAllocateOrderDetailRequest.builder().id(subId).build();
//                AllocateOrderDetail allocateOrderDetail = allocateOrderDetailService.loadAllocateOrderDetail(loadAllocateOrderDetailRequest);
                AllocateOrderDetailLoadListRequest loadListRequest = new AllocateOrderDetailLoadListRequest();
                loadListRequest.setAllocateOrderCode(featuresUpdateRequest.getMainOrderCode());
                loadListRequest.setLineNo(Integer.parseInt(subId));
                Result<List<AllocateOrderDetail>> allocateOrderDetailList = allocateOrderDetailService.loadAllocateOrderDetailList(loadListRequest);
                if (allocateOrderDetailList == null || CollectionUtils.isEmpty(allocateOrderDetailList.getResult())){
                    throw new FacadeException("OTS-03-005-00-15-072");
                }
                AllocateOrderDetail allocateOrderDetail = allocateOrderDetailList.getResult().get(0);

                Map<String, String> subBizFeaturesMap = FeatureUtil.fromString(allocateOrderDetail.getBizFeatures());
                if (MapUtils.isNotEmpty(subBizFeaturesMapUpdate) && subBizFeaturesMapUpdate.containsKey(subId)){
                    SubFeaturesRequest subFeaturesRequest = subBizFeaturesMapUpdate.get(subId);
                    if (Objects.nonNull(subFeaturesRequest) && MapUtils.isNotEmpty(subFeaturesRequest.getSubBizFeaturesToUpdate())){
                        subBizFeaturesMap.putAll(subFeaturesRequest.getSubBizFeaturesToUpdate());
                    }
                }
                if (MapUtils.isNotEmpty(subBizFeaturesMapDelete) && subBizFeaturesMapDelete.containsKey(subId)){
                    SubFeaturesRequest subFeaturesRequest = subBizFeaturesMapDelete.get(subId);
                    if (Objects.nonNull(subFeaturesRequest)){
                        Nullable.stream(subFeaturesRequest.getSubBizFeaturesToDelete()).forEach(subBizFeaturesMap::remove);
                    }
                }
                //TODO 这里是否需要调用更新updateFeatures 方法
                //收发货数量问题; 这里要同步写入收发货数量
                String shipQuantity = subBizFeaturesMap.get(FeaturesKey.CUMULATIVE_DELIVERY_QUANTITY);
                String receiveQuantity = subBizFeaturesMap.get(FeaturesKey.CUMULATIVE_RECEIVED_QUANTITY);
                UpdateQuantityAndBizFeaturesRequest updateQuantityAndBizFeaturesRequest = UpdateQuantityAndBizFeaturesRequest.builder()
                        .mainOrderCode(featuresUpdateRequest.getMainOrderCode())
                        .lineNo(subId)
                        .bizFeatures(FeatureUtil.toString(subBizFeaturesMap))
                        .shipQuantity(StringUtils.isBlank(shipQuantity) ? 0 : new BigDecimal(shipQuantity.trim()).intValue())
                        .receiveQuantity(StringUtils.isBlank(receiveQuantity) ? 0 : new BigDecimal(receiveQuantity.trim()).intValue()).build();
                log.info("detail_updateFeatures_request:{}",JSON.toJSONString(updateQuantityAndBizFeaturesRequest));

                allocateOrderDetailService.updateQuantityAndBizFeatures(updateQuantityAndBizFeaturesRequest);
            });
        }


        return Result.success(null);
    }
}
